summaryrefslogtreecommitdiff
path: root/boost
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:24:45 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:24:45 +0900
commit5ce1cfc2525b06c0a9e38531813781de0281c96d (patch)
tree19cc66c6cf6396db288813b2558cc350f1deede2 /boost
parent3c1df2168531ad5580076ae08d529054689aeedd (diff)
downloadboost-5ce1cfc2525b06c0a9e38531813781de0281c96d.tar.gz
boost-5ce1cfc2525b06c0a9e38531813781de0281c96d.tar.bz2
boost-5ce1cfc2525b06c0a9e38531813781de0281c96d.zip
Imported Upstream version 1.71.0upstream/1.71.0
Diffstat (limited to 'boost')
-rw-r--r--boost/accumulators/accumulators_fwd.hpp66
-rw-r--r--boost/accumulators/framework/accumulator_set.hpp229
-rw-r--r--boost/accumulators/framework/accumulators/external_accumulator.hpp2
-rw-r--r--boost/accumulators/framework/accumulators/reference_accumulator.hpp2
-rw-r--r--boost/accumulators/framework/accumulators/value_accumulator.hpp2
-rw-r--r--boost/accumulators/framework/depends_on.hpp9
-rw-r--r--boost/accumulators/framework/extractor.hpp31
-rw-r--r--boost/accumulators/framework/parameters/accumulator.hpp4
-rw-r--r--boost/accumulators/framework/parameters/sample.hpp4
-rw-r--r--boost/accumulators/framework/parameters/weight.hpp4
-rw-r--r--boost/accumulators/framework/parameters/weights.hpp4
-rw-r--r--boost/accumulators/statistics/count.hpp7
-rw-r--r--boost/accumulators/statistics/covariance.hpp7
-rw-r--r--boost/accumulators/statistics/density.hpp16
-rw-r--r--boost/accumulators/statistics/extended_p_square.hpp14
-rw-r--r--boost/accumulators/statistics/extended_p_square_quantile.hpp11
-rw-r--r--boost/accumulators/statistics/kurtosis.hpp4
-rw-r--r--boost/accumulators/statistics/max.hpp7
-rw-r--r--boost/accumulators/statistics/mean.hpp10
-rw-r--r--boost/accumulators/statistics/median.hpp23
-rw-r--r--boost/accumulators/statistics/min.hpp7
-rw-r--r--boost/accumulators/statistics/moment.hpp7
-rw-r--r--boost/accumulators/statistics/p_square_cumul_dist.hpp16
-rw-r--r--boost/accumulators/statistics/p_square_quantile.hpp42
-rw-r--r--boost/accumulators/statistics/peaks_over_threshold.hpp29
-rw-r--r--boost/accumulators/statistics/pot_quantile.hpp7
-rw-r--r--boost/accumulators/statistics/pot_tail_mean.hpp8
-rw-r--r--boost/accumulators/statistics/rolling_count.hpp4
-rw-r--r--boost/accumulators/statistics/rolling_mean.hpp23
-rw-r--r--boost/accumulators/statistics/rolling_moment.hpp7
-rw-r--r--boost/accumulators/statistics/rolling_sum.hpp7
-rw-r--r--boost/accumulators/statistics/rolling_variance.hpp12
-rw-r--r--boost/accumulators/statistics/rolling_window.hpp49
-rw-r--r--boost/accumulators/statistics/skewness.hpp4
-rw-r--r--boost/accumulators/statistics/sum.hpp7
-rw-r--r--boost/accumulators/statistics/sum_kahan.hpp8
-rw-r--r--boost/accumulators/statistics/tail.hpp11
-rw-r--r--boost/accumulators/statistics/tail_mean.hpp8
-rw-r--r--boost/accumulators/statistics/tail_quantile.hpp4
-rw-r--r--boost/accumulators/statistics/tail_variate.hpp9
-rw-r--r--boost/accumulators/statistics/tail_variate_means.hpp8
-rw-r--r--boost/accumulators/statistics/variance.hpp11
-rw-r--r--boost/accumulators/statistics/weighted_covariance.hpp7
-rw-r--r--boost/accumulators/statistics/weighted_density.hpp16
-rw-r--r--boost/accumulators/statistics/weighted_extended_p_square.hpp12
-rw-r--r--boost/accumulators/statistics/weighted_mean.hpp7
-rw-r--r--boost/accumulators/statistics/weighted_median.hpp18
-rw-r--r--boost/accumulators/statistics/weighted_moment.hpp7
-rw-r--r--boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp13
-rw-r--r--boost/accumulators/statistics/weighted_p_square_quantile.hpp11
-rw-r--r--boost/accumulators/statistics/weighted_peaks_over_threshold.hpp13
-rw-r--r--boost/accumulators/statistics/weighted_sum.hpp7
-rw-r--r--boost/accumulators/statistics/weighted_sum_kahan.hpp8
-rw-r--r--boost/accumulators/statistics/weighted_tail_variate_means.hpp7
-rw-r--r--boost/accumulators/statistics/weighted_variance.hpp7
-rw-r--r--boost/algorithm/find_backward.hpp2
-rw-r--r--boost/algorithm/find_not.hpp2
-rw-r--r--boost/algorithm/string/iter_find.hpp8
-rw-r--r--boost/algorithm/string/split.hpp12
-rw-r--r--boost/align/align_down.hpp8
-rw-r--r--boost/align/align_up.hpp8
-rw-r--r--boost/align/aligned_allocator.hpp41
-rw-r--r--boost/align/aligned_allocator_adaptor.hpp4
-rw-r--r--boost/align/alignment_of.hpp4
-rw-r--r--boost/align/detail/add_reference.hpp44
-rw-r--r--boost/align/detail/addressof.hpp33
-rw-r--r--boost/align/detail/integral_constant.hpp5
-rw-r--r--boost/align/detail/is_aligned.hpp4
-rw-r--r--boost/align/detail/not_pointer.hpp27
-rw-r--r--boost/align/detail/throw_exception.hpp44
-rw-r--r--boost/align/is_aligned.hpp8
-rw-r--r--boost/any.hpp10
-rw-r--r--boost/asio/basic_serial_port.hpp4
-rw-r--r--boost/asio/buffer.hpp2
-rw-r--r--boost/asio/detail/config.hpp14
-rw-r--r--boost/asio/detail/impl/win_iocp_handle_service.ipp3
-rw-r--r--boost/asio/detail/impl/win_iocp_serial_port_service.ipp15
-rw-r--r--boost/asio/detail/impl/win_iocp_socket_service_base.ipp3
-rw-r--r--boost/asio/detail/io_object_executor.hpp7
-rw-r--r--boost/asio/detail/is_buffer_sequence.hpp30
-rw-r--r--boost/asio/detail/winrt_ssocket_service.hpp8
-rw-r--r--boost/asio/detail/winrt_ssocket_service_base.hpp8
-rw-r--r--boost/asio/impl/connect.hpp4
-rw-r--r--boost/asio/ssl/detail/impl/openssl_init.ipp4
-rw-r--r--boost/asio/ssl/detail/openssl_types.hpp3
-rw-r--r--boost/asio/ssl/error.hpp4
-rw-r--r--boost/asio/ssl/impl/context.ipp28
-rw-r--r--boost/asio/version.hpp2
-rw-r--r--boost/beast/_experimental/http/impl/icy_stream.hpp4
-rw-r--r--boost/beast/_experimental/test/impl/stream.hpp7
-rw-r--r--boost/beast/_experimental/test/impl/stream.ipp6
-rw-r--r--boost/beast/_experimental/test/stream.hpp16
-rw-r--r--boost/beast/_experimental/unit_test/thread.hpp128
-rw-r--r--boost/beast/core/basic_stream.hpp157
-rw-r--r--boost/beast/core/buffers_cat.hpp20
-rw-r--r--boost/beast/core/detail/base64.hpp21
-rw-r--r--boost/beast/core/detail/base64.ipp18
-rw-r--r--boost/beast/core/detail/buffers_range_adaptor.hpp17
-rw-r--r--boost/beast/core/detail/char_buffer.hpp78
-rw-r--r--boost/beast/core/detail/impl/read.hpp19
-rw-r--r--boost/beast/core/detail/impl/temporary_buffer.ipp69
-rw-r--r--boost/beast/core/detail/ostream.hpp1
-rw-r--r--boost/beast/core/detail/remap_post_to_defer.hpp1
-rw-r--r--boost/beast/core/detail/service_base.hpp9
-rw-r--r--boost/beast/core/detail/sha1.hpp3
-rw-r--r--boost/beast/core/detail/string.hpp44
-rw-r--r--boost/beast/core/detail/temporary_buffer.hpp83
-rw-r--r--boost/beast/core/detail/type_traits.hpp42
-rw-r--r--boost/beast/core/detail/variant.hpp20
-rw-r--r--boost/beast/core/detect_ssl.hpp3
-rw-r--r--boost/beast/core/impl/async_base.hpp24
-rw-r--r--boost/beast/core/impl/basic_stream.hpp116
-rw-r--r--boost/beast/core/impl/buffered_read_stream.hpp2
-rw-r--r--boost/beast/core/impl/buffers_adaptor.hpp1
-rw-r--r--boost/beast/core/impl/buffers_cat.hpp29
-rw-r--r--boost/beast/core/impl/flat_buffer.hpp2
-rw-r--r--boost/beast/core/impl/flat_stream.hpp2
-rw-r--r--boost/beast/core/impl/multi_buffer.hpp81
-rw-r--r--boost/beast/core/impl/read_size.hpp1
-rw-r--r--boost/beast/core/impl/static_buffer.hpp5
-rw-r--r--boost/beast/core/impl/static_buffer.ipp4
-rw-r--r--boost/beast/core/impl/static_string.hpp59
-rw-r--r--boost/beast/core/impl/string.ipp73
-rw-r--r--boost/beast/core/multi_buffer.hpp66
-rw-r--r--boost/beast/core/rate_policy.hpp2
-rw-r--r--boost/beast/core/span.hpp6
-rw-r--r--boost/beast/core/static_buffer.hpp8
-rw-r--r--boost/beast/core/static_string.hpp3
-rw-r--r--boost/beast/core/string.hpp98
-rw-r--r--boost/beast/core/string_param.hpp1
-rw-r--r--boost/beast/core/string_type.hpp45
-rw-r--r--boost/beast/http/basic_dynamic_body.hpp3
-rw-r--r--boost/beast/http/detail/basic_parser.hpp6
-rw-r--r--boost/beast/http/detail/basic_parser.ipp93
-rw-r--r--boost/beast/http/detail/rfc7230.hpp8
-rw-r--r--boost/beast/http/detail/rfc7230.ipp6
-rw-r--r--boost/beast/http/fields.hpp6
-rw-r--r--boost/beast/http/impl/basic_parser.ipp29
-rw-r--r--boost/beast/http/impl/fields.hpp277
-rw-r--r--boost/beast/http/impl/fields.ipp138
-rw-r--r--boost/beast/http/impl/file_body_win32.hpp1
-rw-r--r--boost/beast/http/impl/message.hpp1
-rw-r--r--boost/beast/http/impl/read.hpp8
-rw-r--r--boost/beast/http/impl/rfc7230.hpp34
-rw-r--r--boost/beast/http/impl/rfc7230.ipp31
-rw-r--r--boost/beast/http/impl/verb.ipp167
-rw-r--r--boost/beast/http/impl/write.hpp11
-rw-r--r--boost/beast/http/rfc7230.hpp12
-rw-r--r--boost/beast/http/string_body.hpp1
-rw-r--r--boost/beast/http/vector_body.hpp4
-rw-r--r--boost/beast/src.hpp4
-rw-r--r--boost/beast/ssl/ssl_stream.hpp42
-rw-r--r--boost/beast/version.hpp2
-rw-r--r--boost/beast/websocket/detail/decorator.hpp9
-rw-r--r--boost/beast/websocket/detail/frame.hpp126
-rw-r--r--boost/beast/websocket/detail/hybi13.ipp21
-rw-r--r--boost/beast/websocket/detail/mask.hpp55
-rw-r--r--boost/beast/websocket/detail/mask.ipp66
-rw-r--r--boost/beast/websocket/detail/pmd_extension.ipp10
-rw-r--r--boost/beast/websocket/detail/prng.hpp79
-rw-r--r--boost/beast/websocket/detail/prng.ipp294
-rw-r--r--boost/beast/websocket/impl/accept.hpp14
-rw-r--r--boost/beast/websocket/impl/close.hpp2
-rw-r--r--boost/beast/websocket/impl/handshake.hpp2
-rw-r--r--boost/beast/websocket/impl/ping.hpp7
-rw-r--r--boost/beast/websocket/impl/read.hpp23
-rw-r--r--boost/beast/websocket/impl/stream.hpp12
-rw-r--r--boost/beast/websocket/impl/stream_impl.hpp56
-rw-r--r--boost/beast/websocket/impl/teardown.hpp4
-rw-r--r--boost/beast/websocket/impl/write.hpp2
-rw-r--r--boost/beast/websocket/option.hpp9
-rw-r--r--boost/beast/websocket/stream.hpp3
-rw-r--r--boost/beast/zlib/detail/deflate_stream.hpp1
-rw-r--r--boost/beast/zlib/detail/deflate_stream.ipp2
-rw-r--r--boost/bind/bind.hpp10
-rw-r--r--boost/bind/mem_fn.hpp22
-rw-r--r--boost/circular_buffer.hpp13
-rw-r--r--boost/circular_buffer/base.hpp174
-rw-r--r--boost/circular_buffer/space_optimized.hpp56
-rw-r--r--boost/config/auto_link.hpp8
-rw-r--r--boost/config/compiler/gcc.hpp6
-rw-r--r--boost/config/compiler/visualc.hpp16
-rw-r--r--boost/config/detail/suffix.hpp21
-rw-r--r--boost/config/platform/vxworks.hpp135
-rw-r--r--boost/config/stdlib/dinkumware.hpp3
-rw-r--r--boost/config/stdlib/libcpp.hpp1
-rw-r--r--boost/config/stdlib/libstdcpp3.hpp1
-rw-r--r--boost/container/adaptive_pool.hpp8
-rw-r--r--boost/container/allocator.hpp4
-rw-r--r--boost/container/allocator_traits.hpp6
-rw-r--r--boost/container/container_fwd.hpp19
-rw-r--r--boost/container/deque.hpp193
-rw-r--r--boost/container/detail/advanced_insert_int.hpp14
-rw-r--r--boost/container/detail/container_rebind.hpp137
-rw-r--r--boost/container/detail/copy_move_algo.hpp7
-rw-r--r--boost/container/detail/flat_tree.hpp40
-rw-r--r--boost/container/detail/mpl.hpp4
-rw-r--r--boost/container/detail/thread_mutex.hpp10
-rw-r--r--boost/container/detail/tree.hpp74
-rw-r--r--boost/container/detail/version_type.hpp7
-rw-r--r--boost/container/flat_map.hpp40
-rw-r--r--boost/container/flat_set.hpp24
-rw-r--r--boost/container/list.hpp50
-rw-r--r--boost/container/map.hpp24
-rw-r--r--boost/container/new_allocator.hpp19
-rw-r--r--boost/container/options.hpp280
-rw-r--r--boost/container/pmr/resource_adaptor.hpp96
-rw-r--r--boost/container/set.hpp14
-rw-r--r--boost/container/slist.hpp50
-rw-r--r--boost/container/small_vector.hpp167
-rw-r--r--boost/container/stable_vector.hpp56
-rw-r--r--boost/container/static_vector.hpp214
-rw-r--r--boost/container/string.hpp50
-rw-r--r--boost/container/vector.hpp49
-rw-r--r--boost/convert/base.hpp19
-rw-r--r--boost/convert/detail/range.hpp2
-rw-r--r--boost/convert/stream.hpp23
-rw-r--r--boost/convert/strtol.hpp18
-rw-r--r--boost/core/alloc_construct.hpp245
-rw-r--r--boost/core/default_allocator.hpp158
-rw-r--r--boost/core/empty_value.hpp8
-rw-r--r--boost/core/first_scalar.hpp45
-rw-r--r--boost/core/lightweight_test.hpp8
-rw-r--r--boost/core/lightweight_test_trait.hpp52
-rw-r--r--boost/core/no_exceptions_support.hpp14
-rw-r--r--boost/core/noinit_adaptor.hpp112
-rw-r--r--boost/core/typeinfo.hpp4
-rw-r--r--boost/core/uncaught_exceptions.hpp7
-rw-r--r--boost/date_time/gregorian/greg_date.hpp2
-rw-r--r--boost/detail/interlocked.hpp235
-rw-r--r--boost/detail/sp_typeinfo.hpp3
-rw-r--r--boost/dynamic_bitset/detail/dynamic_bitset.hpp230
-rw-r--r--boost/dynamic_bitset/dynamic_bitset.hpp39
-rw-r--r--boost/endian/arithmetic.hpp360
-rw-r--r--boost/endian/buffers.hpp425
-rw-r--r--boost/endian/conversion.hpp529
-rw-r--r--boost/endian/detail/cover_operators.hpp142
-rw-r--r--boost/endian/detail/endian_load.hpp589
-rw-r--r--boost/endian/detail/endian_reverse.hpp103
-rw-r--r--boost/endian/detail/endian_store.hpp442
-rw-r--r--boost/endian/detail/integral_by_size.hpp47
-rw-r--r--boost/endian/detail/is_trivially_copyable.hpp39
-rw-r--r--boost/endian/detail/lightweight_test.hpp223
-rw-r--r--boost/endian/detail/order.hpp35
-rw-r--r--boost/endian/endian.hpp99
-rw-r--r--boost/endian/std_pair.hpp38
-rw-r--r--boost/exception/detail/error_info_impl.hpp6
-rw-r--r--boost/exception/detail/exception_ptr.hpp8
-rw-r--r--boost/exception/diagnostic_information.hpp8
-rw-r--r--boost/exception/exception.hpp16
-rw-r--r--boost/exception/info.hpp2
-rw-r--r--boost/filesystem/path.hpp18
-rw-r--r--boost/flyweight/detail/default_value_policy.hpp9
-rw-r--r--boost/foreach.hpp19
-rw-r--r--boost/function/function_base.hpp16
-rw-r--r--boost/geometry/algorithms/buffer.hpp13
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp36
-rw-r--r--boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp41
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp17
-rw-r--r--boost/geometry/algorithms/detail/comparable_distance/interface.hpp19
-rw-r--r--boost/geometry/algorithms/detail/direction_code.hpp63
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp61
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp58
-rw-r--r--boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp26
-rw-r--r--boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp9
-rw-r--r--boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp20
-rw-r--r--boost/geometry/algorithms/detail/distance/point_to_geometry.hpp12
-rw-r--r--boost/geometry/algorithms/detail/distance/segment_to_box.hpp25
-rw-r--r--boost/geometry/algorithms/detail/distance/segment_to_segment.hpp5
-rw-r--r--boost/geometry/algorithms/detail/equals/collect_vectors.hpp23
-rw-r--r--boost/geometry/algorithms/detail/get_left_turns.hpp16
-rw-r--r--boost/geometry/algorithms/detail/has_self_intersections.hpp6
-rw-r--r--boost/geometry/algorithms/detail/intersection/interface.hpp49
-rw-r--r--boost/geometry/algorithms/detail/is_simple/areal.hpp55
-rw-r--r--boost/geometry/algorithms/detail/is_simple/linear.hpp63
-rw-r--r--boost/geometry/algorithms/detail/is_simple/multipoint.hpp15
-rw-r--r--boost/geometry/algorithms/detail/is_valid/complement_graph.hpp10
-rw-r--r--boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp10
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp11
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_spikes.hpp82
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp11
-rw-r--r--boost/geometry/algorithms/detail/is_valid/linear.hpp8
-rw-r--r--boost/geometry/algorithms/detail/is_valid/multipolygon.hpp22
-rw-r--r--boost/geometry/algorithms/detail/is_valid/polygon.hpp50
-rw-r--r--boost/geometry/algorithms/detail/is_valid/ring.hpp31
-rw-r--r--boost/geometry/algorithms/detail/is_valid/segment.hpp9
-rw-r--r--boost/geometry/algorithms/detail/overlay/assign_parents.hpp18
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp41
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp174
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_ring.hpp15
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info.hpp294
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp49
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp48
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp36
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_colocations.hpp118
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp124
-rw-r--r--boost/geometry/algorithms/detail/overlay/intersection_insert.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/linear_linear.hpp18
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay.hpp12
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp17
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/sort_by_side.hpp35
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal.hpp41
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp2
-rw-r--r--boost/geometry/algorithms/detail/overlay/turn_info.hpp2
-rw-r--r--boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp8
-rw-r--r--boost/geometry/algorithms/detail/relate/areal_areal.hpp9
-rw-r--r--boost/geometry/algorithms/detail/relate/boundary_checker.hpp8
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_areal.hpp16
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_linear.hpp9
-rw-r--r--boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp36
-rw-r--r--boost/geometry/algorithms/detail/relate/point_point.hpp17
-rw-r--r--boost/geometry/algorithms/detail/relate/topology_check.hpp3
-rw-r--r--boost/geometry/algorithms/detail/relate/turns.hpp44
-rw-r--r--boost/geometry/algorithms/detail/within/multi_point.hpp43
-rw-r--r--boost/geometry/algorithms/difference.hpp42
-rw-r--r--boost/geometry/algorithms/sym_difference.hpp42
-rw-r--r--boost/geometry/algorithms/union.hpp52
-rw-r--r--boost/geometry/core/config.hpp5
-rw-r--r--boost/geometry/formulas/differential_quantities.hpp3
-rw-r--r--boost/geometry/formulas/thomas_direct.hpp3
-rw-r--r--boost/geometry/index/detail/algorithms/bounds.hpp184
-rw-r--r--boost/geometry/index/detail/algorithms/intersection_content.hpp40
-rw-r--r--boost/geometry/index/detail/bounded_view.hpp146
-rw-r--r--boost/geometry/index/detail/distance_predicates.hpp187
-rw-r--r--boost/geometry/index/detail/predicates.hpp200
-rw-r--r--boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp43
-rw-r--r--boost/geometry/index/detail/rtree/node/node.hpp20
-rw-r--r--boost/geometry/index/detail/rtree/options.hpp19
-rw-r--r--boost/geometry/index/detail/rtree/pack_create.hpp31
-rw-r--r--boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp41
-rw-r--r--boost/geometry/index/detail/rtree/query_iterators.hpp18
-rw-r--r--boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp45
-rw-r--r--boost/geometry/index/detail/rtree/rstar/insert.hpp57
-rw-r--r--boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp86
-rw-r--r--boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp23
-rw-r--r--boost/geometry/index/detail/rtree/visitors/children_box.hpp21
-rw-r--r--boost/geometry/index/detail/rtree/visitors/count.hpp39
-rw-r--r--boost/geometry/index/detail/rtree/visitors/distance_query.hpp58
-rw-r--r--boost/geometry/index/detail/rtree/visitors/insert.hpp20
-rw-r--r--boost/geometry/index/detail/rtree/visitors/remove.hpp20
-rw-r--r--boost/geometry/index/detail/rtree/visitors/spatial_query.hpp54
-rw-r--r--boost/geometry/index/detail/translator.hpp41
-rw-r--r--boost/geometry/index/equal_to.hpp119
-rw-r--r--boost/geometry/index/parameters.hpp76
-rw-r--r--boost/geometry/index/rtree.hpp65
-rw-r--r--boost/geometry/io/wkt/write.hpp9
-rw-r--r--boost/geometry/policies/compare.hpp148
-rw-r--r--boost/geometry/policies/robustness/get_rescale_policy.hpp257
-rw-r--r--boost/geometry/srs/projections/proj/cea.hpp2
-rw-r--r--boost/geometry/strategies/agnostic/point_in_poly_winding.hpp8
-rw-r--r--boost/geometry/strategies/cartesian/box_in_box.hpp196
-rw-r--r--boost/geometry/strategies/cartesian/disjoint_segment_box.hpp22
-rw-r--r--boost/geometry/strategies/cartesian/distance_projected_point.hpp25
-rw-r--r--boost/geometry/strategies/cartesian/distance_segment_box.hpp22
-rw-r--r--boost/geometry/strategies/cartesian/envelope_box.hpp13
-rw-r--r--boost/geometry/strategies/cartesian/index.hpp197
-rw-r--r--boost/geometry/strategies/cartesian/intersection.hpp37
-rw-r--r--boost/geometry/strategies/cartesian/point_in_point.hpp6
-rw-r--r--boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp40
-rw-r--r--boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp62
-rw-r--r--boost/geometry/strategies/cartesian/point_in_poly_winding.hpp93
-rw-r--r--boost/geometry/strategies/cartesian/side_by_triangle.hpp6
-rw-r--r--boost/geometry/strategies/concepts/within_concept.hpp23
-rw-r--r--boost/geometry/strategies/geographic/buffer_point_circle.hpp6
-rw-r--r--boost/geometry/strategies/geographic/disjoint_segment_box.hpp24
-rw-r--r--boost/geometry/strategies/geographic/distance_cross_track.hpp584
-rw-r--r--boost/geometry/strategies/geographic/distance_segment_box.hpp32
-rw-r--r--boost/geometry/strategies/geographic/index.hpp216
-rw-r--r--boost/geometry/strategies/geographic/intersection.hpp6
-rw-r--r--boost/geometry/strategies/geographic/point_in_poly_winding.hpp15
-rw-r--r--boost/geometry/strategies/geographic/side.hpp11
-rw-r--r--boost/geometry/strategies/index.hpp71
-rw-r--r--boost/geometry/strategies/spherical/compare.hpp22
-rw-r--r--boost/geometry/strategies/spherical/disjoint_segment_box.hpp19
-rw-r--r--boost/geometry/strategies/spherical/distance_cross_track.hpp45
-rw-r--r--boost/geometry/strategies/spherical/distance_segment_box.hpp46
-rw-r--r--boost/geometry/strategies/spherical/envelope_box.hpp81
-rw-r--r--boost/geometry/strategies/spherical/expand_box.hpp91
-rw-r--r--boost/geometry/strategies/spherical/index.hpp198
-rw-r--r--boost/geometry/strategies/spherical/intersection.hpp5
-rw-r--r--boost/geometry/strategies/spherical/point_in_point.hpp7
-rw-r--r--boost/geometry/strategies/spherical/point_in_poly_winding.hpp180
-rw-r--r--boost/geometry/strategies/spherical/ssf.hpp6
-rw-r--r--boost/geometry/strategies/strategies.hpp22
-rw-r--r--boost/geometry/strategies/transform/matrix_transformers.hpp9
-rw-r--r--boost/geometry/util/range.hpp8
-rw-r--r--boost/graph/adjacency_matrix.hpp6
-rw-r--r--boost/graph/astar_search.hpp343
-rw-r--r--boost/graph/bipartite.hpp6
-rw-r--r--boost/graph/boyer_myrvold_planar_test.hpp180
-rw-r--r--boost/graph/breadth_first_search.hpp9
-rw-r--r--boost/graph/bron_kerbosch_all_cliques.hpp2
-rw-r--r--boost/graph/connected_components.hpp5
-rw-r--r--boost/graph/copy.hpp2
-rw-r--r--boost/graph/cycle_canceling.hpp44
-rw-r--r--boost/graph/depth_first_search.hpp7
-rw-r--r--boost/graph/detail/adjacency_list.hpp13
-rw-r--r--boost/graph/detail/array_binary_tree.hpp8
-rw-r--r--boost/graph/detail/empty_header.hpp10
-rw-r--r--boost/graph/detail/geodesic.hpp2
-rw-r--r--boost/graph/detail/mpi_include.hpp16
-rw-r--r--boost/graph/detail/read_graphviz_new.hpp6
-rw-r--r--boost/graph/detail/read_graphviz_spirit.hpp6
-rw-r--r--boost/graph/dijkstra_shortest_paths.hpp46
-rw-r--r--boost/graph/dijkstra_shortest_paths_no_color_map.hpp59
-rw-r--r--boost/graph/dimacs.hpp2
-rw-r--r--boost/graph/distributed/detail/mpi_process_group.ipp14
-rw-r--r--boost/graph/exception.hpp12
-rw-r--r--boost/graph/exterior_property.hpp5
-rw-r--r--boost/graph/fruchterman_reingold.hpp5
-rw-r--r--boost/graph/graph_test.hpp384
-rw-r--r--boost/graph/graphml.hpp8
-rw-r--r--boost/graph/graphviz.hpp15
-rw-r--r--boost/graph/gursoy_atun_layout.hpp4
-rw-r--r--boost/graph/isomorphism.hpp1
-rw-r--r--boost/graph/loop_erased_random_walk.hpp2
-rw-r--r--boost/graph/matrix_as_graph.hpp14
-rw-r--r--boost/graph/max_cardinality_matching.hpp2
-rw-r--r--boost/graph/maximum_adjacency_search.hpp48
-rw-r--r--boost/graph/maximum_weighted_matching.hpp1167
-rw-r--r--boost/graph/metis.hpp4
-rw-r--r--boost/graph/minimum_degree_ordering.hpp13
-rw-r--r--boost/graph/named_function_params.hpp79
-rw-r--r--boost/graph/one_bit_color_map.hpp7
-rw-r--r--boost/graph/page_rank.hpp5
-rw-r--r--boost/graph/parallel/distribution.hpp10
-rw-r--r--boost/graph/planar_detail/boyer_myrvold_impl.hpp3
-rw-r--r--boost/graph/profile.hpp3
-rw-r--r--boost/graph/r_c_shortest_paths.hpp658
-rw-r--r--boost/graph/random_spanning_tree.hpp26
-rw-r--r--boost/graph/relax.hpp31
-rw-r--r--boost/graph/rmat_graph_generator.hpp5
-rw-r--r--boost/graph/sloan_ordering.hpp3
-rw-r--r--boost/graph/stanford_graph.hpp1
-rw-r--r--boost/graph/stoer_wagner_min_cut.hpp3
-rw-r--r--boost/graph/strong_components.hpp5
-rw-r--r--boost/graph/subgraph.hpp118
-rw-r--r--boost/graph/successive_shortest_path_nonnegative_weights.hpp76
-rw-r--r--boost/graph/two_bit_color_map.hpp7
-rw-r--r--boost/graph/vector_as_graph.hpp9
-rw-r--r--boost/graph/wavefront.hpp3
-rw-r--r--boost/hana/basic_tuple.hpp10
-rw-r--r--boost/hana/config.hpp30
-rw-r--r--boost/hana/detail/integral_constant.hpp4
-rw-r--r--boost/hana/detail/preprocessor.hpp5
-rw-r--r--boost/hana/detail/struct_macros.hpp35
-rw-r--r--boost/hana/detail/variadic/reverse_apply.hpp4
-rw-r--r--boost/hana/experimental/printable.hpp2
-rw-r--r--boost/hana/functional/apply.hpp2
-rw-r--r--boost/hana/functional/curry.hpp4
-rw-r--r--boost/hana/fwd/ap.hpp7
-rw-r--r--boost/hana/fwd/concept/comparable.hpp2
-rw-r--r--boost/hana/fwd/concept/constant.hpp2
-rw-r--r--boost/hana/fwd/concept/metafunction.hpp2
-rw-r--r--boost/hana/fwd/concept/orderable.hpp2
-rw-r--r--boost/hana/pair.hpp4
-rw-r--r--boost/hana/string.hpp2
-rw-r--r--boost/hana/tuple.hpp10
-rw-r--r--boost/hana/version.hpp2
-rw-r--r--boost/heap/detail/stable_heap.hpp10
-rw-r--r--boost/heap/policies.hpp6
-rw-r--r--boost/histogram.hpp14
-rw-r--r--boost/histogram/accumulators.hpp16
-rw-r--r--boost/histogram/accumulators/ostream.hpp27
-rw-r--r--boost/histogram/accumulators/thread_safe.hpp57
-rw-r--r--boost/histogram/algorithm/project.hpp28
-rw-r--r--boost/histogram/algorithm/reduce.hpp249
-rw-r--r--boost/histogram/algorithm/sum.hpp2
-rw-r--r--boost/histogram/axis/category.hpp29
-rw-r--r--boost/histogram/axis/integer.hpp24
-rw-r--r--boost/histogram/axis/iterator.hpp33
-rw-r--r--boost/histogram/axis/ostream.hpp26
-rw-r--r--boost/histogram/axis/polymorphic_bin.hpp15
-rw-r--r--boost/histogram/axis/regular.hpp68
-rw-r--r--boost/histogram/axis/traits.hpp232
-rw-r--r--boost/histogram/axis/variable.hpp46
-rw-r--r--boost/histogram/axis/variant.hpp226
-rw-r--r--boost/histogram/detail/args_type.hpp38
-rw-r--r--boost/histogram/detail/attribute.hpp4
-rw-r--r--boost/histogram/detail/axes.hpp116
-rw-r--r--boost/histogram/detail/common_type.hpp53
-rw-r--r--boost/histogram/detail/compressed_pair.hpp84
-rw-r--r--boost/histogram/detail/convert_integer.hpp24
-rw-r--r--boost/histogram/detail/detect.hpp209
-rw-r--r--boost/histogram/detail/iterator_adaptor.hpp162
-rw-r--r--boost/histogram/detail/large_int.hpp227
-rw-r--r--boost/histogram/detail/limits.hpp50
-rw-r--r--boost/histogram/detail/linearize.hpp296
-rw-r--r--boost/histogram/detail/make_default.hpp27
-rw-r--r--boost/histogram/detail/meta.hpp436
-rw-r--r--boost/histogram/detail/noop_mutex.hpp24
-rw-r--r--boost/histogram/detail/operators.hpp135
-rw-r--r--boost/histogram/detail/relaxed_equal.hpp28
-rw-r--r--boost/histogram/detail/replace_default.hpp25
-rw-r--r--boost/histogram/detail/safe_comparison.hpp87
-rw-r--r--boost/histogram/detail/static_if.hpp46
-rw-r--r--boost/histogram/detail/try_cast.hpp49
-rw-r--r--boost/histogram/detail/tuple_slice.hpp34
-rw-r--r--boost/histogram/detail/type_name.hpp51
-rw-r--r--boost/histogram/fwd.hpp23
-rw-r--r--boost/histogram/histogram.hpp299
-rw-r--r--boost/histogram/indexed.hpp337
-rw-r--r--boost/histogram/make_histogram.hpp18
-rw-r--r--boost/histogram/ostream.hpp11
-rw-r--r--boost/histogram/serialization.hpp88
-rw-r--r--boost/histogram/storage_adaptor.hpp185
-rw-r--r--boost/histogram/unlimited_storage.hpp949
-rw-r--r--boost/histogram/unsafe_access.hpp35
-rw-r--r--boost/interprocess/detail/os_file_functions.hpp4
-rw-r--r--boost/interprocess/detail/win32_api.hpp8
-rw-r--r--boost/interprocess/streams/bufferstream.hpp2
-rw-r--r--boost/intrusive/detail/workaround.hpp5
-rw-r--r--boost/intrusive/pack_options.hpp6
-rw-r--r--boost/intrusive/treap.hpp2
-rw-r--r--boost/intrusive/treap_set.hpp4
-rw-r--r--boost/iostreams/detail/adapter/concept_adapter.hpp4
-rw-r--r--boost/iostreams/detail/functional.hpp16
-rw-r--r--boost/iostreams/filter/bzip2.hpp34
-rw-r--r--boost/iostreams/filter/lzma.hpp14
-rw-r--r--boost/lockfree/policies.hpp2
-rw-r--r--boost/lockfree/queue.hpp2
-rw-r--r--boost/log/detail/sink_init_helpers.hpp63
-rw-r--r--boost/log/expressions/formatters.hpp1
-rw-r--r--boost/log/expressions/formatters/auto_newline.hpp46
-rw-r--r--boost/log/keywords/auto_newline_mode.hpp40
-rw-r--r--boost/log/sinks/auto_newline_mode.hpp47
-rw-r--r--boost/log/sinks/text_file_backend.hpp14
-rw-r--r--boost/log/sinks/text_multifile_backend.hpp36
-rw-r--r--boost/log/sinks/text_ostream_backend.hpp53
-rw-r--r--boost/log/sources/record_ostream.hpp14
-rw-r--r--boost/log/trivial.hpp18
-rw-r--r--boost/log/utility/formatting_ostream.hpp65
-rw-r--r--boost/log/utility/manipulators.hpp1
-rw-r--r--boost/log/utility/manipulators/auto_newline.hpp66
-rw-r--r--boost/log/utility/manipulators/dump.hpp4
-rw-r--r--boost/log/utility/setup/console.hpp22
-rw-r--r--boost/log/utility/setup/file.hpp4
-rw-r--r--boost/math/cstdfloat/cstdfloat_cmath.hpp1560
-rw-r--r--boost/math/differentiation/autodiff.hpp2053
-rw-r--r--boost/math/differentiation/autodiff_cpp11.hpp383
-rw-r--r--boost/math/interpolators/cardinal_quadratic_b_spline.hpp57
-rw-r--r--boost/math/interpolators/catmull_rom.hpp64
-rw-r--r--boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp206
-rw-r--r--boost/math/interpolators/detail/vector_barycentric_rational_detail.hpp193
-rw-r--r--boost/math/interpolators/detail/whittaker_shannon_detail.hpp126
-rw-r--r--boost/math/interpolators/vector_barycentric_rational.hpp82
-rw-r--r--boost/math/interpolators/whittaker_shannon.hpp47
-rw-r--r--boost/math/quadrature/detail/ooura_fourier_integrals_detail.hpp651
-rw-r--r--boost/math/quadrature/ooura_fourier_integrals.hpp68
-rw-r--r--boost/math/special_functions/beta.hpp7
-rw-r--r--boost/math/special_functions/cos_pi.hpp7
-rw-r--r--boost/math/special_functions/detail/unchecked_factorial.hpp42
-rw-r--r--boost/math/special_functions/ellint_1.hpp14
-rw-r--r--boost/math/special_functions/ellint_2.hpp13
-rw-r--r--boost/math/special_functions/ellint_3.hpp19
-rw-r--r--boost/math/special_functions/ellint_d.hpp2
-rw-r--r--boost/math/special_functions/lambert_w.hpp28
-rw-r--r--boost/math/special_functions/prime.hpp2
-rw-r--r--boost/math/special_functions/sin_pi.hpp13
-rw-r--r--boost/math/special_functions/trunc.hpp51
-rw-r--r--boost/math/tools/roots.hpp175
-rw-r--r--boost/math/tools/univariate_statistics.hpp43
-rw-r--r--boost/metaparse/config.hpp10
-rw-r--r--boost/metaparse/v1/cpp11/impl/any_of_c.hpp33
-rw-r--r--boost/metaparse/v1/cpp11/impl/eval_later_result.hpp39
-rw-r--r--boost/metaparse/v1/cpp11/impl/is_none_c.hpp33
-rw-r--r--boost/metaparse/v1/cpp11/impl/is_none_c_impl.hpp36
-rw-r--r--boost/metaparse/v1/cpp11/impl/or_c.hpp36
-rw-r--r--boost/metaparse/v1/cpp11/impl/push_front_result.hpp36
-rw-r--r--boost/metaparse/v1/cpp11/impl/remove_trailing_no_chars.hpp55
-rw-r--r--boost/metaparse/v1/cpp11/impl/string_at.hpp6
-rw-r--r--boost/metaparse/v1/cpp11/one_char_except.hpp33
-rw-r--r--boost/metaparse/v1/cpp11/one_char_except_c.hpp33
-rw-r--r--boost/metaparse/v1/cpp11/one_of.hpp56
-rw-r--r--boost/metaparse/v1/cpp11/one_of_c.hpp35
-rw-r--r--boost/metaparse/v1/cpp11/repeated_one_of.hpp25
-rw-r--r--boost/metaparse/v1/cpp11/repeated_one_of1.hpp25
-rw-r--r--boost/metaparse/v1/cpp11/sequence.hpp62
-rw-r--r--boost/metaparse/v1/cpp11/string.hpp2
-rw-r--r--boost/metaparse/v1/cpp14/impl/any_of_c.hpp55
-rw-r--r--boost/metaparse/v1/cpp14/one_of_c.hpp35
-rw-r--r--boost/metaparse/v1/cpp98/impl/is_none.hpp (renamed from boost/metaparse/v1/impl/is_any.hpp)20
-rw-r--r--boost/metaparse/v1/cpp98/impl/later_result.hpp (renamed from boost/metaparse/v1/impl/later_result.hpp)4
-rw-r--r--boost/metaparse/v1/cpp98/impl/one_char_except_not_used.hpp (renamed from boost/metaparse/v1/impl/one_char_except_not_used.hpp)4
-rw-r--r--boost/metaparse/v1/cpp98/impl/one_of.hpp (renamed from boost/metaparse/v1/impl/one_of.hpp)2
-rw-r--r--boost/metaparse/v1/cpp98/impl/one_of_fwd_op.hpp (renamed from boost/metaparse/v1/impl/one_of_fwd_op.hpp)2
-rw-r--r--boost/metaparse/v1/cpp98/impl/sequence.hpp (renamed from boost/metaparse/v1/impl/sequence.hpp)6
-rw-r--r--boost/metaparse/v1/cpp98/impl/sequence_impl.hpp (renamed from boost/metaparse/v1/impl/sequence_impl.hpp)4
-rw-r--r--boost/metaparse/v1/cpp98/one_char_except.hpp84
-rw-r--r--boost/metaparse/v1/cpp98/one_char_except_c.hpp96
-rw-r--r--boost/metaparse/v1/cpp98/one_of.hpp42
-rw-r--r--boost/metaparse/v1/cpp98/one_of_c.hpp81
-rw-r--r--boost/metaparse/v1/cpp98/repeated_one_of.hpp45
-rw-r--r--boost/metaparse/v1/cpp98/repeated_one_of1.hpp45
-rw-r--r--boost/metaparse/v1/cpp98/sequence.hpp64
-rw-r--r--boost/metaparse/v1/one_char_except.hpp81
-rw-r--r--boost/metaparse/v1/one_char_except_c.hpp92
-rw-r--r--boost/metaparse/v1/one_of.hpp38
-rw-r--r--boost/metaparse/v1/one_of_c.hpp78
-rw-r--r--boost/metaparse/v1/repeated_one_of.hpp41
-rw-r--r--boost/metaparse/v1/repeated_one_of1.hpp41
-rw-r--r--boost/metaparse/v1/sequence.hpp60
-rw-r--r--boost/move/algo/adaptive_sort.hpp10
-rw-r--r--boost/move/algo/detail/set_difference.hpp2
-rw-r--r--boost/mp11/detail/config.hpp16
-rw-r--r--boost/mp11/detail/mp_count.hpp4
-rw-r--r--boost/mp11/function.hpp6
-rw-r--r--boost/mp11/version.hpp2
-rw-r--r--boost/mpi/collectives/all_gather.hpp4
-rw-r--r--boost/mpi/collectives/gather.hpp4
-rw-r--r--boost/mpi/collectives/scatter.hpp4
-rw-r--r--boost/mpi/communicator.hpp483
-rw-r--r--boost/mpi/config.hpp31
-rw-r--r--boost/mpi/datatype.hpp12
-rw-r--r--boost/mpi/detail/antiques.hpp4
-rw-r--r--boost/mpi/detail/broadcast_sc.hpp17
-rw-r--r--boost/mpi/detail/communicator_sc.hpp38
-rw-r--r--boost/mpi/detail/mpi_datatype_primitive.hpp6
-rw-r--r--boost/mpi/detail/offsets.hpp5
-rw-r--r--boost/mpi/detail/point_to_point.hpp27
-rw-r--r--boost/mpi/detail/request_handlers.hpp631
-rw-r--r--boost/mpi/nonblocking.hpp63
-rw-r--r--boost/mpi/operations.hpp5
-rw-r--r--boost/mpi/request.hpp136
-rw-r--r--boost/mpi/skeleton_and_content.hpp330
-rw-r--r--boost/mpi/skeleton_and_content_types.hpp363
-rw-r--r--boost/mpi/status.hpp1
-rw-r--r--boost/mpl/if.hpp2
-rw-r--r--boost/multi_array.hpp6
-rw-r--r--boost/multi_array/allocators.hpp72
-rw-r--r--boost/multi_index/detail/is_function.hpp52
-rw-r--r--boost/multi_index/key.hpp76
-rw-r--r--boost/multi_index/mem_fun.hpp96
-rw-r--r--boost/multiprecision/concepts/mp_number_archetypes.hpp2
-rw-r--r--boost/multiprecision/cpp_bin_float.hpp2
-rw-r--r--boost/multiprecision/cpp_bin_float/io.hpp2
-rw-r--r--boost/multiprecision/cpp_bin_float/transcendental.hpp2
-rw-r--r--boost/multiprecision/cpp_dec_float.hpp7
-rw-r--r--boost/multiprecision/cpp_int.hpp16
-rw-r--r--boost/multiprecision/cpp_int/add.hpp2
-rw-r--r--boost/multiprecision/cpp_int/bitwise.hpp2
-rw-r--r--boost/multiprecision/cpp_int/checked.hpp2
-rw-r--r--boost/multiprecision/cpp_int/comparison.hpp2
-rw-r--r--boost/multiprecision/cpp_int/cpp_int_config.hpp2
-rw-r--r--boost/multiprecision/cpp_int/divide.hpp2
-rw-r--r--boost/multiprecision/cpp_int/import_export.hpp2
-rw-r--r--boost/multiprecision/cpp_int/limits.hpp2
-rw-r--r--boost/multiprecision/cpp_int/literals.hpp2
-rw-r--r--boost/multiprecision/cpp_int/misc.hpp2
-rw-r--r--boost/multiprecision/cpp_int/multiply.hpp2
-rw-r--r--boost/multiprecision/cpp_int/serialize.hpp2
-rw-r--r--boost/multiprecision/cpp_int/value_pack.hpp2
-rw-r--r--boost/multiprecision/debug_adaptor.hpp4
-rw-r--r--boost/multiprecision/detail/bitscan.hpp2
-rw-r--r--boost/multiprecision/detail/digits.hpp2
-rw-r--r--boost/multiprecision/detail/float_string_cvt.hpp2
-rw-r--r--boost/multiprecision/detail/generic_interconvert.hpp9
-rw-r--r--boost/multiprecision/detail/integer_ops.hpp2
-rw-r--r--boost/multiprecision/float128.hpp16
-rw-r--r--boost/multiprecision/gmp.hpp7
-rw-r--r--boost/multiprecision/integer.hpp2
-rw-r--r--boost/multiprecision/logged_adaptor.hpp2
-rw-r--r--boost/multiprecision/miller_rabin.hpp2
-rw-r--r--boost/multiprecision/mpc.hpp2
-rw-r--r--boost/multiprecision/number.hpp5
-rw-r--r--boost/multiprecision/random.hpp2
-rw-r--r--boost/multiprecision/rational_adaptor.hpp2
-rw-r--r--boost/multiprecision/tommath.hpp6
-rw-r--r--boost/multiprecision/traits/extract_exponent_type.hpp2
-rw-r--r--boost/numeric/conversion/converter_policies.hpp7
-rw-r--r--boost/numeric/interval/detail/x86gcc_rounding_control.hpp2
-rw-r--r--boost/numeric/odeint.hpp3
-rw-r--r--boost/numeric/odeint/algebra/multi_array_algebra.hpp18
-rw-r--r--boost/numeric/odeint/algebra/vector_space_algebra.hpp2
-rw-r--r--boost/numeric/odeint/external/eigen/eigen_algebra.hpp45
-rw-r--r--boost/numeric/odeint/stepper/adaptive_adams_bashforth_moulton.hpp237
-rw-r--r--boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp7
-rw-r--r--boost/numeric/odeint/stepper/controlled_adams_bashforth_moulton.hpp322
-rw-r--r--boost/numeric/odeint/stepper/controlled_runge_kutta.hpp24
-rw-r--r--boost/numeric/odeint/stepper/dense_output_runge_kutta.hpp2
-rw-r--r--boost/numeric/odeint/stepper/detail/adaptive_adams_coefficients.hpp207
-rw-r--r--boost/numeric/odeint/stepper/detail/pid_step_adjuster.hpp199
-rw-r--r--boost/numeric/odeint/stepper/detail/pid_step_adjuster_coefficients.hpp180
-rw-r--r--boost/numeric/odeint/stepper/generation.hpp1
-rw-r--r--boost/numeric/odeint/stepper/generation/generation_controlled_adams_bashforth_moulton.hpp59
-rw-r--r--boost/numeric/odeint/stepper/rosenbrock4_controller.hpp2
-rw-r--r--boost/numeric/odeint/stepper/rosenbrock4_dense_output.hpp19
-rw-r--r--boost/outcome.hpp2
-rw-r--r--boost/outcome/bad_access.hpp2
-rw-r--r--boost/outcome/basic_outcome.hpp183
-rw-r--r--boost/outcome/basic_result.hpp11
-rw-r--r--boost/outcome/boost_outcome.hpp5
-rw-r--r--boost/outcome/boost_result.hpp2
-rw-r--r--boost/outcome/config.hpp18
-rw-r--r--boost/outcome/convert.hpp13
-rw-r--r--boost/outcome/detail/basic_outcome_exception_observers.hpp2
-rw-r--r--boost/outcome/detail/basic_outcome_exception_observers_impl.hpp2
-rw-r--r--boost/outcome/detail/basic_outcome_failure_observers.hpp2
-rw-r--r--boost/outcome/detail/basic_result_error_observers.hpp2
-rw-r--r--boost/outcome/detail/basic_result_final.hpp3
-rw-r--r--boost/outcome/detail/basic_result_storage.hpp53
-rw-r--r--boost/outcome/detail/basic_result_value_observers.hpp2
-rw-r--r--boost/outcome/detail/revision.hpp33
-rw-r--r--boost/outcome/detail/trait_std_error_code.hpp2
-rw-r--r--boost/outcome/detail/trait_std_exception.hpp2
-rw-r--r--boost/outcome/detail/value_storage.hpp109
-rw-r--r--boost/outcome/detail/version.hpp42
-rw-r--r--boost/outcome/experimental/result.h2
-rw-r--r--boost/outcome/experimental/status-code/config.hpp43
-rw-r--r--boost/outcome/experimental/status_outcome.hpp2
-rw-r--r--boost/outcome/experimental/status_result.hpp2
-rw-r--r--boost/outcome/iostream_support.hpp2
-rw-r--r--boost/outcome/outcome.hpp2
-rw-r--r--boost/outcome/policy/all_narrow.hpp2
-rw-r--r--boost/outcome/policy/base.hpp2
-rw-r--r--boost/outcome/policy/fail_to_compile_observers.hpp2
-rw-r--r--boost/outcome/policy/outcome_error_code_throw_as_system_error.hpp2
-rw-r--r--boost/outcome/policy/outcome_exception_ptr_rethrow.hpp2
-rw-r--r--boost/outcome/policy/result_error_code_throw_as_system_error.hpp2
-rw-r--r--boost/outcome/policy/result_exception_ptr_rethrow.hpp2
-rw-r--r--boost/outcome/policy/terminate.hpp2
-rw-r--r--boost/outcome/policy/throw_bad_result_access.hpp2
-rw-r--r--boost/outcome/result.hpp2
-rw-r--r--boost/outcome/revision.hpp4
-rw-r--r--boost/outcome/std_outcome.hpp5
-rw-r--r--boost/outcome/std_result.hpp2
-rw-r--r--boost/outcome/success_failure.hpp2
-rw-r--r--boost/outcome/trait.hpp6
-rw-r--r--boost/outcome/try.hpp124
-rw-r--r--boost/outcome/utils.hpp2
-rw-r--r--boost/outcome/version.hpp13
-rw-r--r--boost/parameter.hpp17
-rw-r--r--boost/parameter/are_tagged_arguments.hpp125
-rw-r--r--boost/parameter/aux_/always_true_predicate.hpp42
-rw-r--r--boost/parameter/aux_/arg_list.hpp1606
-rw-r--r--boost/parameter/aux_/as_lvalue.hpp25
-rw-r--r--boost/parameter/aux_/augment_predicate.hpp198
-rw-r--r--boost/parameter/aux_/cast.hpp143
-rw-r--r--boost/parameter/aux_/default.hpp147
-rw-r--r--boost/parameter/aux_/has_nested_template_fn.hpp111
-rw-r--r--boost/parameter/aux_/is_maybe.hpp58
-rw-r--r--boost/parameter/aux_/is_placeholder.hpp64
-rw-r--r--boost/parameter/aux_/is_tagged_argument.hpp95
-rw-r--r--boost/parameter/aux_/lambda_tag.hpp16
-rw-r--r--boost/parameter/aux_/maybe.hpp225
-rw-r--r--boost/parameter/aux_/name.hpp93
-rw-r--r--boost/parameter/aux_/overloads.hpp88
-rw-r--r--boost/parameter/aux_/pack/as_parameter_requirements.hpp32
-rw-r--r--boost/parameter/aux_/pack/deduce_tag.hpp217
-rw-r--r--boost/parameter/aux_/pack/deduced_item.hpp34
-rw-r--r--boost/parameter/aux_/pack/insert_tagged.hpp23
-rw-r--r--boost/parameter/aux_/pack/is_named_argument.hpp43
-rw-r--r--boost/parameter/aux_/pack/item.hpp47
-rw-r--r--boost/parameter/aux_/pack/make_arg_list.hpp438
-rw-r--r--boost/parameter/aux_/pack/make_deduced_items.hpp53
-rw-r--r--boost/parameter/aux_/pack/make_items.hpp45
-rw-r--r--boost/parameter/aux_/pack/make_parameter_spec_items.hpp244
-rw-r--r--boost/parameter/aux_/pack/parameter_requirements.hpp25
-rw-r--r--boost/parameter/aux_/pack/predicate.hpp87
-rw-r--r--boost/parameter/aux_/pack/satisfies.hpp142
-rw-r--r--boost/parameter/aux_/pack/tag_deduced.hpp59
-rw-r--r--boost/parameter/aux_/pack/tag_keyword_arg.hpp30
-rw-r--r--boost/parameter/aux_/pack/tag_keyword_arg_ref.hpp67
-rw-r--r--boost/parameter/aux_/pack/tag_template_keyword_arg.hpp30
-rw-r--r--boost/parameter/aux_/pack/tag_type.hpp89
-rw-r--r--boost/parameter/aux_/pack/unmatched_argument.hpp41
-rw-r--r--boost/parameter/aux_/parameter_requirements.hpp23
-rw-r--r--boost/parameter/aux_/parenthesized_type.hpp39
-rw-r--r--boost/parameter/aux_/pp_impl/argument_pack.hpp91
-rw-r--r--boost/parameter/aux_/pp_impl/match.hpp55
-rw-r--r--boost/parameter/aux_/pp_impl/unwrap_predicate.hpp97
-rw-r--r--boost/parameter/aux_/preprocessor/binary_seq_for_each.hpp1638
-rw-r--r--boost/parameter/aux_/preprocessor/binary_seq_for_each_inc.hpp1796
-rw-r--r--boost/parameter/aux_/preprocessor/binary_seq_to_args.hpp65
-rw-r--r--boost/parameter/aux_/preprocessor/convert_binary_seq.hpp57
-rw-r--r--boost/parameter/aux_/preprocessor/flatten.hpp117
-rw-r--r--boost/parameter/aux_/preprocessor/for_each.hpp105
-rw-r--r--boost/parameter/aux_/preprocessor/for_each_pred.hpp1029
-rw-r--r--boost/parameter/aux_/preprocessor/impl/argument_specs.hpp24
-rw-r--r--boost/parameter/aux_/preprocessor/impl/arity_range.hpp42
-rw-r--r--boost/parameter/aux_/preprocessor/impl/flatten.hpp143
-rw-r--r--boost/parameter/aux_/preprocessor/impl/for_each.hpp152
-rw-r--r--boost/parameter/aux_/preprocessor/impl/forwarding_overloads.hpp509
-rw-r--r--boost/parameter/aux_/preprocessor/impl/function_cast.hpp730
-rw-r--r--boost/parameter/aux_/preprocessor/impl/function_dispatch_layer.hpp474
-rw-r--r--boost/parameter/aux_/preprocessor/impl/function_dispatch_tuple.hpp33
-rw-r--r--boost/parameter/aux_/preprocessor/impl/function_forward_match.hpp43
-rw-r--r--boost/parameter/aux_/preprocessor/impl/function_name.hpp152
-rw-r--r--boost/parameter/aux_/preprocessor/impl/no_spec_overloads.hpp331
-rw-r--r--boost/parameter/aux_/preprocessor/impl/parenthesized_return_type.hpp122
-rw-r--r--boost/parameter/aux_/preprocessor/impl/parenthesized_type.hpp34
-rw-r--r--boost/parameter/aux_/preprocessor/impl/specification.hpp109
-rw-r--r--boost/parameter/aux_/preprocessor/impl/split_args.hpp71
-rw-r--r--boost/parameter/aux_/preprocessor/inc_binary_seq.hpp78
-rw-r--r--boost/parameter/aux_/preprocessor/is_binary.hpp31
-rw-r--r--boost/parameter/aux_/preprocessor/is_nullary.hpp32
-rw-r--r--boost/parameter/aux_/preprocessor/no_perfect_forwarding_begin.hpp165
-rw-r--r--boost/parameter/aux_/preprocessor/no_perfect_forwarding_end.hpp24
-rw-r--r--boost/parameter/aux_/preprocessor/nullptr.hpp18
-rw-r--r--boost/parameter/aux_/preprocessor/overloads.hpp92
-rw-r--r--boost/parameter/aux_/preprocessor/qualifier.hpp88
-rw-r--r--boost/parameter/aux_/preprocessor/seq_enum.hpp26
-rw-r--r--boost/parameter/aux_/preprocessor/seq_merge.hpp1807
-rw-r--r--boost/parameter/aux_/result_of0.hpp75
-rw-r--r--boost/parameter/aux_/set.hpp136
-rw-r--r--boost/parameter/aux_/tag.hpp176
-rw-r--r--boost/parameter/aux_/tagged_argument.hpp1024
-rw-r--r--boost/parameter/aux_/tagged_argument_fwd.hpp38
-rw-r--r--boost/parameter/aux_/template_keyword.hpp110
-rw-r--r--boost/parameter/aux_/unwrap_cv_reference.hpp231
-rw-r--r--boost/parameter/aux_/use_default.hpp17
-rw-r--r--boost/parameter/aux_/use_default_tag.hpp29
-rw-r--r--boost/parameter/aux_/void.hpp41
-rw-r--r--boost/parameter/aux_/yesno.hpp40
-rw-r--r--boost/parameter/binding.hpp224
-rw-r--r--boost/parameter/compose.hpp210
-rw-r--r--boost/parameter/config.hpp81
-rw-r--r--boost/parameter/deduced.hpp132
-rw-r--r--boost/parameter/is_argument_pack.hpp29
-rw-r--r--boost/parameter/keyword.hpp822
-rw-r--r--boost/parameter/keyword_fwd.hpp23
-rw-r--r--boost/parameter/macros.hpp277
-rw-r--r--boost/parameter/match.hpp81
-rw-r--r--boost/parameter/name.hpp226
-rw-r--r--boost/parameter/nested_keyword.hpp111
-rw-r--r--boost/parameter/optional.hpp67
-rw-r--r--boost/parameter/parameters.hpp1437
-rw-r--r--boost/parameter/preprocessor.hpp1172
-rw-r--r--boost/parameter/preprocessor_no_spec.hpp74
-rw-r--r--boost/parameter/required.hpp66
-rw-r--r--boost/parameter/template_keyword.hpp87
-rw-r--r--boost/parameter/value_type.hpp222
-rw-r--r--boost/pending/bucket_sorter.hpp37
-rw-r--r--boost/pending/property_serialize.hpp23
-rw-r--r--boost/pending/relaxed_heap.hpp4
-rw-r--r--boost/poly_collection/detail/stride_iterator.hpp33
-rw-r--r--boost/polygon/detail/voronoi_ctypes.hpp1
-rw-r--r--boost/process.hpp1
-rw-r--r--boost/process/detail/child_decl.hpp15
-rw-r--r--boost/process/detail/posix/async_in.hpp18
-rw-r--r--boost/process/detail/posix/async_out.hpp16
-rw-r--r--boost/process/detail/posix/basic_pipe.hpp2
-rw-r--r--boost/process/detail/posix/close_in.hpp6
-rw-r--r--boost/process/detail/posix/close_out.hpp5
-rw-r--r--boost/process/detail/posix/executor.hpp195
-rw-r--r--boost/process/detail/posix/fd.hpp16
-rw-r--r--boost/process/detail/posix/file_in.hpp8
-rw-r--r--boost/process/detail/posix/file_out.hpp12
-rw-r--r--boost/process/detail/posix/handles.hpp146
-rw-r--r--boost/process/detail/posix/null_in.hpp10
-rw-r--r--boost/process/detail/posix/null_out.hpp14
-rw-r--r--boost/process/detail/posix/pipe_in.hpp14
-rw-r--r--boost/process/detail/posix/pipe_out.hpp14
-rw-r--r--boost/process/detail/posix/terminate.hpp2
-rw-r--r--boost/process/detail/posix/wait_for_exit.hpp66
-rw-r--r--boost/process/detail/posix/wait_group.hpp115
-rw-r--r--boost/process/detail/used_handles.hpp81
-rw-r--r--boost/process/detail/windows/async_in.hpp10
-rw-r--r--boost/process/detail/windows/async_out.hpp9
-rw-r--r--boost/process/detail/windows/async_pipe.hpp105
-rw-r--r--boost/process/detail/windows/basic_pipe.hpp4
-rw-r--r--boost/process/detail/windows/file_in.hpp6
-rw-r--r--boost/process/detail/windows/file_out.hpp7
-rw-r--r--boost/process/detail/windows/group_ref.hpp7
-rw-r--r--boost/process/detail/windows/handle_workaround.hpp262
-rw-r--r--boost/process/detail/windows/handles.hpp176
-rw-r--r--boost/process/detail/windows/null_in.hpp6
-rw-r--r--boost/process/detail/windows/null_out.hpp5
-rw-r--r--boost/process/detail/windows/pipe_in.hpp5
-rw-r--r--boost/process/detail/windows/pipe_out.hpp5
-rw-r--r--boost/process/detail/windows/wait_group.hpp6
-rw-r--r--boost/process/extend.hpp4
-rw-r--r--boost/process/handles.hpp107
-rw-r--r--boost/process/pipe.hpp124
-rw-r--r--boost/proto/debug.hpp25
-rw-r--r--boost/proto/proto_fwd.hpp2
-rw-r--r--boost/ptr_container/ptr_vector.hpp27
-rw-r--r--boost/qvm/quat_operations.hpp6
-rw-r--r--boost/range/algorithm/max_element.hpp40
-rw-r--r--boost/range/algorithm/min_element.hpp40
-rw-r--r--boost/range/detail/less.hpp26
-rw-r--r--boost/rational.hpp40
-rw-r--r--boost/safe_numerics/checked_float.hpp27
-rw-r--r--boost/safe_numerics/exception.hpp2
-rw-r--r--boost/safe_numerics/safe_base_operations.hpp1
-rw-r--r--boost/safe_numerics/safe_integer.hpp1
-rw-r--r--boost/safe_numerics/utility.hpp30
-rw-r--r--boost/signals2/detail/auto_buffer.hpp20
-rw-r--r--boost/signals2/detail/scope_guard.hpp110
-rw-r--r--boost/signals2/detail/signal_template.hpp4
-rw-r--r--boost/signals2/detail/slot_call_iterator.hpp21
-rw-r--r--boost/signals2/signal_type.hpp41
-rw-r--r--boost/smart_ptr/allocate_local_shared_array.hpp113
-rw-r--r--boost/smart_ptr/allocate_shared_array.hpp374
-rw-r--r--boost/smart_ptr/atomic_shared_ptr.hpp9
-rw-r--r--boost/smart_ptr/detail/atomic_count_std_atomic.hpp2
-rw-r--r--boost/smart_ptr/detail/shared_count.hpp4
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_aix.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_clang.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_nt.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_pt.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_solaris.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_spin.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_sync.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_w32.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_counted_impl.hpp20
-rw-r--r--boost/smart_ptr/detail/sp_typeinfo_.hpp58
-rw-r--r--boost/smart_ptr/enable_shared_from.hpp37
-rw-r--r--boost/smart_ptr/enable_shared_from_raw.hpp3
-rw-r--r--boost/smart_ptr/intrusive_ptr.hpp27
-rw-r--r--boost/smart_ptr/make_local_shared_array.hpp25
-rw-r--r--boost/smart_ptr/make_shared_array.hpp25
-rw-r--r--boost/smart_ptr/shared_array.hpp4
-rw-r--r--boost/smart_ptr/shared_ptr.hpp10
-rw-r--r--boost/smart_ptr/weak_ptr.hpp29
-rw-r--r--boost/spirit/home/karma/auto/auto.hpp3
-rw-r--r--boost/spirit/home/karma/auxiliary/lazy.hpp3
-rw-r--r--boost/spirit/home/karma/detail/alternative_function.hpp6
-rw-r--r--boost/spirit/home/karma/detail/fail_function.hpp3
-rw-r--r--boost/spirit/home/karma/detail/pass_container.hpp3
-rw-r--r--boost/spirit/home/karma/detail/unused_delimiter.hpp3
-rw-r--r--boost/spirit/home/karma/directive/columns.hpp3
-rw-r--r--boost/spirit/home/karma/directive/repeat.hpp9
-rw-r--r--boost/spirit/home/karma/stream/detail/format_manip.hpp9
-rw-r--r--boost/spirit/home/karma/stream/detail/iterator_sink.hpp3
-rw-r--r--boost/spirit/home/karma/stream/stream.hpp3
-rw-r--r--boost/spirit/home/karma/string/symbols.hpp12
-rw-r--r--boost/spirit/home/lex/detail/sequence_function.hpp6
-rw-r--r--boost/spirit/home/lex/lexer/action.hpp3
-rw-r--r--boost/spirit/home/lex/lexer/lexer.hpp9
-rw-r--r--boost/spirit/home/lex/lexer/lexertl/functor.hpp3
-rw-r--r--boost/spirit/home/lex/lexer/lexertl/functor_data.hpp14
-rw-r--r--boost/spirit/home/lex/lexer/lexertl/lexer.hpp3
-rw-r--r--boost/spirit/home/lex/lexer/lexertl/static_functor_data.hpp12
-rw-r--r--boost/spirit/home/lex/lexer/lexertl/static_lexer.hpp3
-rw-r--r--boost/spirit/home/lex/qi/state_switcher.hpp6
-rw-r--r--boost/spirit/home/lex/tokenize_and_parse_attr.hpp48
-rw-r--r--boost/spirit/home/qi/action/action.hpp3
-rw-r--r--boost/spirit/home/qi/auxiliary/attr.hpp3
-rw-r--r--boost/spirit/home/qi/auxiliary/attr_cast.hpp3
-rw-r--r--boost/spirit/home/qi/detail/alternative_function.hpp6
-rw-r--r--boost/spirit/home/qi/detail/expect_function.hpp3
-rw-r--r--boost/spirit/home/qi/detail/fail_function.hpp3
-rw-r--r--boost/spirit/home/qi/detail/pass_container.hpp3
-rw-r--r--boost/spirit/home/qi/detail/pass_function.hpp3
-rw-r--r--boost/spirit/home/qi/detail/permute_function.hpp3
-rw-r--r--boost/spirit/home/qi/detail/unused_skipper.hpp3
-rw-r--r--boost/spirit/home/qi/directive/matches.hpp3
-rw-r--r--boost/spirit/home/qi/directive/omit.hpp3
-rw-r--r--boost/spirit/home/qi/directive/repeat.hpp12
-rw-r--r--boost/spirit/home/qi/numeric/detail/real_impl.hpp60
-rw-r--r--boost/spirit/home/qi/numeric/real_policies.hpp45
-rw-r--r--boost/spirit/home/qi/stream/detail/iterator_source.hpp3
-rw-r--r--boost/spirit/home/qi/stream/detail/match_manip.hpp9
-rw-r--r--boost/spirit/home/qi/string/lit.hpp3
-rw-r--r--boost/spirit/home/qi/string/symbols.hpp6
-rw-r--r--boost/spirit/home/support/detail/hold_any.hpp24
-rw-r--r--boost/spirit/home/support/detail/what_function.hpp3
-rw-r--r--boost/spirit/home/support/info.hpp6
-rw-r--r--boost/spirit/home/support/iterators/detail/split_functor_input_policy.hpp3
-rw-r--r--boost/spirit/home/support/nonterminal/expand_arg.hpp3
-rw-r--r--boost/spirit/home/support/terminal.hpp9
-rw-r--r--boost/spirit/home/support/unused.hpp25
-rw-r--r--boost/spirit/home/support/utree/detail/utree_detail2.hpp1
-rw-r--r--boost/spirit/home/x3/auxiliary/attr.hpp6
-rw-r--r--boost/spirit/home/x3/char/char_set.hpp13
-rw-r--r--boost/spirit/home/x3/char/unicode.hpp42
-rw-r--r--boost/spirit/home/x3/core/detail/parse_into_container.hpp19
-rw-r--r--boost/spirit/home/x3/directive/raw.hpp16
-rw-r--r--boost/spirit/home/x3/nonterminal/rule.hpp3
-rw-r--r--boost/spirit/home/x3/numeric/real.hpp3
-rw-r--r--boost/spirit/home/x3/operator/detail/alternative.hpp8
-rw-r--r--boost/spirit/home/x3/operator/detail/sequence.hpp10
-rw-r--r--boost/spirit/home/x3/string/literal_string.hpp29
-rw-r--r--boost/spirit/home/x3/support/numeric_utils/extract_real.hpp55
-rw-r--r--boost/spirit/home/x3/support/numeric_utils/pow10.hpp49
-rw-r--r--boost/spirit/home/x3/support/traits/attribute_of.hpp17
-rw-r--r--boost/spirit/home/x3/support/traits/pseudo_attribute.hpp34
-rw-r--r--boost/spirit/home/x3/support/traits/string_traits.hpp147
-rw-r--r--boost/spirit/home/x3/support/unused.hpp25
-rw-r--r--boost/spirit/home/x3/support/utility/testing.hpp269
-rw-r--r--boost/spirit/repository/home/qi/directive/kwd.hpp24
-rw-r--r--boost/spirit/repository/home/qi/operator/detail/keywords.hpp3
-rw-r--r--boost/stacktrace/detail/frame_msvc.ipp10
-rw-r--r--boost/stacktrace/detail/frame_unwind.ipp11
-rw-r--r--boost/stacktrace/detail/libbacktrace_impls.hpp8
-rw-r--r--boost/system/detail/config.hpp16
-rw-r--r--boost/system/detail/std_interoperability.hpp61
-rw-r--r--boost/system/detail/system_category_win32.hpp1
-rw-r--r--boost/system/error_code.hpp16
-rw-r--r--boost/test/auto_unit_test.hpp3
-rw-r--r--boost/test/floating_point_comparison.hpp4
-rw-r--r--boost/test/framework.hpp6
-rw-r--r--boost/test/impl/decorator.ipp2
-rw-r--r--boost/test/impl/execution_monitor.ipp2
-rw-r--r--boost/test/impl/framework.ipp8
-rw-r--r--boost/test/included/unit_test_framework.hpp4
-rw-r--r--boost/test/output_test_stream.hpp4
-rw-r--r--boost/test/predicate_result.hpp4
-rw-r--r--boost/test/test_case_template.hpp4
-rw-r--r--boost/test/tools/floating_point_comparison.hpp21
-rw-r--r--boost/test/unit_test_log_formatter.hpp2
-rw-r--r--boost/test/unit_test_suite.hpp12
-rw-r--r--boost/thread/concurrent_queues/detail/sync_deque_base.hpp28
-rw-r--r--boost/thread/concurrent_queues/detail/sync_queue_base.hpp28
-rw-r--r--boost/thread/concurrent_queues/sync_deque.hpp6
-rw-r--r--boost/thread/concurrent_queues/sync_priority_queue.hpp8
-rw-r--r--boost/thread/concurrent_queues/sync_queue.hpp6
-rw-r--r--boost/thread/concurrent_queues/sync_timed_queue.hpp94
-rw-r--r--boost/thread/pthread/condition_variable.hpp34
-rw-r--r--boost/thread/pthread/condition_variable_fwd.hpp19
-rw-r--r--boost/thread/pthread/mutex.hpp48
-rw-r--r--boost/thread/pthread/once.hpp55
-rw-r--r--boost/thread/pthread/pthread_helpers.hpp181
-rw-r--r--boost/thread/pthread/pthread_mutex_scoped_lock.hpp70
-rw-r--r--boost/thread/pthread/recursive_mutex.hpp38
-rw-r--r--boost/thread/pthread/thread_data.hpp2
-rw-r--r--boost/thread/win32/thread_primitives.hpp2
-rw-r--r--boost/throw_exception.hpp2
-rw-r--r--boost/type_traits/detail/config.hpp14
-rw-r--r--boost/type_traits/detail/is_function_cxx_11.hpp28
-rw-r--r--boost/type_traits/detail/is_member_function_pointer_cxx_11.hpp2
-rw-r--r--boost/utility/ostream_string.hpp95
-rw-r--r--boost/utility/string_ref.hpp45
-rw-r--r--boost/utility/string_view.hpp47
-rw-r--r--boost/uuid/basic_name_generator.hpp2
-rw-r--r--boost/uuid/detail/config.hpp2
-rw-r--r--boost/uuid/detail/md5.hpp49
-rw-r--r--boost/uuid/detail/random_provider.hpp2
-rw-r--r--boost/uuid/detail/random_provider_arc4random.ipp2
-rw-r--r--boost/uuid/detail/random_provider_bcrypt.ipp12
-rw-r--r--boost/uuid/detail/random_provider_detect_platform.hpp10
-rw-r--r--boost/uuid/detail/random_provider_getentropy.ipp2
-rw-r--r--boost/uuid/detail/random_provider_getrandom.ipp2
-rw-r--r--boost/uuid/detail/random_provider_include_platform.hpp2
-rw-r--r--boost/uuid/detail/random_provider_posix.ipp2
-rw-r--r--boost/uuid/detail/random_provider_wincrypt.ipp12
-rw-r--r--boost/uuid/detail/sha1.hpp4
-rw-r--r--boost/uuid/detail/uuid_generic.ipp2
-rw-r--r--boost/uuid/detail/uuid_x86.ipp2
-rw-r--r--boost/uuid/entropy_error.hpp2
-rw-r--r--boost/uuid/name_generator.hpp2
-rw-r--r--boost/uuid/name_generator_md5.hpp2
-rw-r--r--boost/uuid/name_generator_sha1.hpp2
-rw-r--r--boost/uuid/nil_generator.hpp2
-rw-r--r--boost/uuid/random_generator.hpp2
-rw-r--r--boost/uuid/string_generator.hpp2
-rw-r--r--boost/uuid/uuid.hpp2
-rw-r--r--boost/uuid/uuid_generators.hpp2
-rw-r--r--boost/uuid/uuid_hash.hpp6
-rw-r--r--boost/uuid/uuid_io.hpp2
-rw-r--r--boost/uuid/uuid_serialize.hpp2
-rw-r--r--boost/variant/detail/apply_visitor_unary.hpp9
-rw-r--r--boost/variant/detail/forced_return.hpp14
-rw-r--r--boost/variant/detail/std_hash.hpp46
-rw-r--r--boost/variant/detail/visitation_impl.hpp2
-rw-r--r--boost/variant/variant.hpp7
-rw-r--r--boost/variant2/variant.hpp1795
-rw-r--r--boost/version.hpp4
-rw-r--r--boost/yap/user_macros.hpp4
1072 files changed, 51507 insertions, 17619 deletions
diff --git a/boost/accumulators/accumulators_fwd.hpp b/boost/accumulators/accumulators_fwd.hpp
index 4c0370e21e..fabc4e8406 100644
--- a/boost/accumulators/accumulators_fwd.hpp
+++ b/boost/accumulators/accumulators_fwd.hpp
@@ -9,6 +9,8 @@
#define BOOST_ACCUMULATORS_ACCUMULATORS_FWD_HPP_EAN_28_10_2005
#include <boost/config.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/parameter/is_argument_pack.hpp>
#include <boost/mpl/apply_fwd.hpp> // for mpl::na
#include <boost/mpl/limits/vector.hpp>
#include <boost/preprocessor/cat.hpp>
@@ -41,7 +43,6 @@
#endif
#ifdef BOOST_ACCUMULATORS_BROKEN_CONST_OVERLOADS
-# include <boost/utility/enable_if.hpp>
# include <boost/type_traits/is_const.hpp>
# define BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(T)\
, typename boost::disable_if<boost::is_const<T> >::type * = 0
@@ -128,9 +129,12 @@ template<typename Feature, typename AccumulatorSet>
typename mpl::apply<AccumulatorSet, Feature>::type::result_type
extract_result(AccumulatorSet const &acc);
-template<typename Feature, typename AccumulatorSet, typename A1>
-typename mpl::apply<AccumulatorSet, Feature>::type::result_type
-extract_result(AccumulatorSet const &acc, A1 const &a1);
+namespace detail
+{
+ struct _enabler
+ {
+ };
+}
// ... other overloads generated by Boost.Preprocessor:
@@ -146,17 +150,37 @@ extract_result(AccumulatorSet const &acc, A1 const &a1);
extract_result( \
AccumulatorSet const &acc \
BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
+ , typename boost::enable_if< \
+ parameter::is_argument_pack<A0> \
+ , detail::_enabler \
+ >::type = detail::_enabler() \
+ ); \
+ template< \
+ typename Feature \
+ , typename AccumulatorSet \
+ BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \
+ > \
+ typename mpl::apply<AccumulatorSet, Feature>::type::result_type \
+ extract_result( \
+ AccumulatorSet const &acc \
+ BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
+ , typename boost::disable_if< \
+ parameter::is_argument_pack<A0> \
+ , detail::_enabler \
+ >::type = detail::_enabler() \
);
/// INTERNAL ONLY
///
BOOST_PP_REPEAT_FROM_TO(
- 2
+ 1
, BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
, BOOST_ACCUMULATORS_EXTRACT_RESULT_FWD
, _
)
+#undef BOOST_ACCUMULATORS_EXTRACT_RESULT_FWD
+
#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
template<typename Feature, typename AccumulatorSet, typename A1, typename A2 ...>
typename mpl::apply<AccumulatorSet, Feature>::type::result_type
@@ -185,6 +209,9 @@ namespace detail
struct is_accumulator_set;
inline void ignore_variable(void const *) {}
+}
+
+}} // namespace boost::accumulators
#define BOOST_ACCUMULATORS_IGNORE_GLOBAL(X) \
namespace detail \
@@ -198,33 +225,8 @@ namespace detail
}; \
} \
/**/
-}
-}} // namespace boost::accumulators
+#include <boost/parameter/nested_keyword.hpp>
-// For defining boost::parameter keywords that can be inherited from to
-// get a nested, class-scoped keyword with the requested alias
-#define BOOST_PARAMETER_NESTED_KEYWORD(tag_namespace, name, alias) \
- namespace tag_namespace \
- { \
- template<int Dummy = 0> \
- struct name ## _ \
- { \
- static char const* keyword_name() \
- { \
- return #name; \
- } \
- static ::boost::parameter::keyword<name ## _<Dummy> > &alias; \
- }; \
- template<int Dummy> \
- ::boost::parameter::keyword<name ## _<Dummy> > &name ## _<Dummy>::alias = \
- ::boost::parameter::keyword<name ## _<Dummy> >::get(); \
- typedef name ## _ <> name; \
- } \
- namespace \
- { \
- ::boost::parameter::keyword<tag_namespace::name> &name = \
- ::boost::parameter::keyword<tag_namespace::name>::get(); \
- }
+#endif // include guard
-#endif
diff --git a/boost/accumulators/framework/accumulator_set.hpp b/boost/accumulators/framework/accumulator_set.hpp
index ed1ceb1afa..0b4f4ad3dc 100644
--- a/boost/accumulators/framework/accumulator_set.hpp
+++ b/boost/accumulators/framework/accumulator_set.hpp
@@ -9,16 +9,23 @@
#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
#include <boost/version.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/protect.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/type_traits/is_same.hpp>
-#include <boost/type_traits/is_base_and_derived.hpp>
-#include <boost/parameter/parameters.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/parameter/is_argument_pack.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/accumulators/accumulators_fwd.hpp>
#include <boost/accumulators/framework/depends_on.hpp>
#include <boost/accumulators/framework/accumulator_concept.hpp>
@@ -64,14 +71,6 @@ namespace detail
return accumulator_visitor<Args>(args);
}
- typedef
- parameter::parameters<
- parameter::required<tag::accumulator>
- , parameter::optional<tag::sample>
- // ... and others which are not specified here...
- >
- accumulator_params;
-
///////////////////////////////////////////////////////////////////////////////
// accumulator_set_base
struct accumulator_set_base
@@ -82,10 +81,38 @@ namespace detail
// is_accumulator_set
template<typename T>
struct is_accumulator_set
- : is_base_and_derived<accumulator_set_base, T>
+ : mpl::if_<
+ boost::is_base_of<
+ accumulator_set_base
+ , typename boost::remove_const<
+ typename boost::remove_reference<T>::type
+ >::type
+ >
+ , mpl::true_
+ , mpl::false_
+ >::type
{
};
+ // function object that serialize an accumulator
+ template<typename Archive>
+ struct serialize_accumulator
+ {
+ serialize_accumulator(Archive & _ar, const unsigned int _file_version) :
+ ar(_ar), file_version(_file_version)
+ {}
+
+ template<typename Accumulator>
+ void operator ()(Accumulator &accumulator)
+ {
+ accumulator.serialize(ar, file_version);
+ }
+
+ private:
+ Archive& ar;
+ const unsigned int file_version;
+ };
+
} // namespace detail
#ifdef _MSC_VER
@@ -140,13 +167,13 @@ struct accumulator_set
: accumulators(
detail::make_acc_list(
accumulators_mpl_vector()
- , detail::accumulator_params()(*this)
+ , (boost::accumulators::accumulator = *this)
)
)
{
// Add-ref the Features that the user has specified
this->template visit_if<detail::contains_feature_of_<Features> >(
- detail::make_add_ref_visitor(detail::accumulator_params()(*this))
+ detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
);
}
@@ -154,17 +181,48 @@ struct accumulator_set
///
/// \param a1 Optional named parameter to be passed to all the accumulators
template<typename A1>
- explicit accumulator_set(A1 const &a1)
- : accumulators(
+ explicit accumulator_set(
+ A1 const &a1
+ , typename boost::enable_if<
+ parameter::is_argument_pack<A1>
+ , detail::_enabler
+ >::type = detail::_enabler()
+ ) : accumulators(
+ detail::make_acc_list(
+ accumulators_mpl_vector()
+ , (boost::accumulators::accumulator = *this, a1)
+ )
+ )
+ {
+ // Add-ref the Features that the user has specified
+ this->template visit_if<detail::contains_feature_of_<Features> >(
+ detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
+ );
+ }
+
+ /// \overload
+ ///
+ /// \param a1 Optional sample parameter to be passed to all the accumulators
+ template<typename A1>
+ explicit accumulator_set(
+ A1 const &a1
+ , typename boost::disable_if<
+ parameter::is_argument_pack<A1>
+ , detail::_enabler
+ >::type = detail::_enabler()
+ ) : accumulators(
detail::make_acc_list(
accumulators_mpl_vector()
- , detail::accumulator_params()(*this, a1)
+ , (
+ boost::accumulators::accumulator = *this
+ , boost::accumulators::sample = a1
+ )
)
)
{
// Add-ref the Features that the user has specified
this->template visit_if<detail::contains_feature_of_<Features> >(
- detail::make_add_ref_visitor(detail::accumulator_params()(*this))
+ detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
);
}
@@ -174,19 +232,47 @@ struct accumulator_set
///
#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR(z, n, _) \
template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- accumulator_set(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \
- : accumulators( \
+ accumulator_set( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
+ , typename boost::enable_if< \
+ parameter::is_argument_pack<A0> \
+ , detail::_enabler \
+ >::type = detail::_enabler() \
+ ) : accumulators( \
detail::make_acc_list( \
accumulators_mpl_vector() \
- , detail::accumulator_params()( \
- *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
+ , ( \
+ boost::accumulators::accumulator = *this \
+ BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
) \
) \
) \
{ \
/* Add-ref the Features that the user has specified */ \
this->template visit_if<detail::contains_feature_of_<Features> >( \
- detail::make_add_ref_visitor(detail::accumulator_params()(*this)) \
+ detail::make_add_ref_visitor(boost::accumulators::accumulator = *this) \
+ ); \
+ } \
+ template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
+ accumulator_set( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
+ , typename boost::disable_if< \
+ parameter::is_argument_pack<A0> \
+ , detail::_enabler \
+ >::type = detail::_enabler() \
+ ) : accumulators( \
+ detail::make_acc_list( \
+ accumulators_mpl_vector() \
+ , ( \
+ boost::accumulators::accumulator = *this \
+ , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
+ ) \
+ ) \
+ ) \
+ { \
+ /* Add-ref the Features that the user has specified */ \
+ this->template visit_if<detail::contains_feature_of_<Features> >( \
+ detail::make_add_ref_visitor(boost::accumulators::accumulator = *this) \
); \
}
@@ -239,17 +325,7 @@ struct accumulator_set
{
this->visit(
detail::make_accumulator_visitor(
- detail::accumulator_params()(*this)
- )
- );
- }
-
- template<typename A1>
- void operator ()(A1 const &a1)
- {
- this->visit(
- detail::make_accumulator_visitor(
- detail::accumulator_params()(*this, a1)
+ boost::accumulators::accumulator = *this
)
);
}
@@ -260,12 +336,37 @@ struct accumulator_set
///
#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP(z, n, _) \
template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- void operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \
+ void operator ()( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
+ , typename boost::enable_if< \
+ parameter::is_argument_pack<A0> \
+ , detail::_enabler \
+ >::type = detail::_enabler() \
+ ) \
{ \
this->visit( \
detail::make_accumulator_visitor( \
- detail::accumulator_params()( \
- *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
+ ( \
+ boost::accumulators::accumulator = *this \
+ BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
+ ) \
+ ) \
+ ); \
+ } \
+ template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
+ void operator ()( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
+ , typename boost::disable_if< \
+ parameter::is_argument_pack<A0> \
+ , detail::_enabler \
+ >::type = detail::_enabler() \
+ ) \
+ { \
+ this->visit( \
+ detail::make_accumulator_visitor( \
+ ( \
+ boost::accumulators::accumulator = *this \
+ , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
) \
) \
); \
@@ -274,7 +375,7 @@ struct accumulator_set
/// INTERNAL ONLY
///
BOOST_PP_REPEAT_FROM_TO(
- 2
+ 1
, BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
, BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP
, _
@@ -329,15 +430,23 @@ struct accumulator_set
the_feature;
(*fusion::find_if<detail::matches_feature<Feature> >(this->accumulators))
- .drop(detail::accumulator_params()(*this));
+ .drop(boost::accumulators::accumulator = *this);
// Also drop accumulators that this feature depends on
typedef typename the_feature::dependencies dependencies;
this->template visit_if<detail::contains_feature_of_<dependencies> >(
- detail::make_drop_visitor(detail::accumulator_params()(*this))
+ detail::make_drop_visitor(boost::accumulators::accumulator = *this)
);
}
+ // make the accumulator set serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ detail::serialize_accumulator<Archive> serializer(ar, file_version);
+ fusion::for_each(this->accumulators, serializer);
+ }
+
private:
accumulators_type accumulators;
@@ -365,6 +474,15 @@ find_accumulator(AccumulatorSet const &acc)
return acc.template extract<Feature>();
}
+template<typename Feature, typename AccumulatorSet>
+typename mpl::apply<AccumulatorSet, Feature>::type::result_type
+extract_result(AccumulatorSet const &acc)
+{
+ return find_accumulator<Feature>(acc).result(
+ boost::accumulators::accumulator = acc
+ );
+}
+
///////////////////////////////////////////////////////////////////////////////
// extract_result
// extract a result from an accumulator set
@@ -380,18 +498,43 @@ find_accumulator(AccumulatorSet const &acc)
extract_result( \
AccumulatorSet const &acc \
BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
+ , typename boost::enable_if< \
+ parameter::is_argument_pack<A0> \
+ , detail::_enabler \
+ >::type \
) \
{ \
return find_accumulator<Feature>(acc).result( \
- detail::accumulator_params()( \
- acc \
+ ( \
+ boost::accumulators::accumulator = acc \
BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
) \
); \
+ } \
+ template< \
+ typename Feature \
+ , typename AccumulatorSet \
+ BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \
+ > \
+ typename mpl::apply<AccumulatorSet, Feature>::type::result_type \
+ extract_result( \
+ AccumulatorSet const &acc \
+ BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
+ , typename boost::disable_if< \
+ parameter::is_argument_pack<A0> \
+ , detail::_enabler \
+ >::type \
+ ) \
+ { \
+ return find_accumulator<Feature>(acc).result(( \
+ boost::accumulators::accumulator = acc \
+ , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
+ )); \
}
-BOOST_PP_REPEAT(
- BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
+BOOST_PP_REPEAT_FROM_TO(
+ 1
+ , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
, BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN
, _
)
diff --git a/boost/accumulators/framework/accumulators/external_accumulator.hpp b/boost/accumulators/framework/accumulators/external_accumulator.hpp
index 71dce42e51..eb6965c0ab 100644
--- a/boost/accumulators/framework/accumulators/external_accumulator.hpp
+++ b/boost/accumulators/framework/accumulators/external_accumulator.hpp
@@ -34,7 +34,7 @@ namespace boost { namespace accumulators { namespace impl
template<typename Args>
result_type result(Args const &args) const
{
- return this->extract_(args, args[parameter::keyword<Tag>::get() | 0]);
+ return this->extract_(args, args[parameter::keyword<Tag>::instance | 0]);
}
private:
diff --git a/boost/accumulators/framework/accumulators/reference_accumulator.hpp b/boost/accumulators/framework/accumulators/reference_accumulator.hpp
index bf4252ca6a..e50a751dc5 100644
--- a/boost/accumulators/framework/accumulators/reference_accumulator.hpp
+++ b/boost/accumulators/framework/accumulators/reference_accumulator.hpp
@@ -31,7 +31,7 @@ namespace impl
template<typename Args>
reference_accumulator_impl(Args const &args)
- : ref(args[parameter::keyword<Tag>::get()])
+ : ref(args[parameter::keyword<Tag>::instance])
{
}
diff --git a/boost/accumulators/framework/accumulators/value_accumulator.hpp b/boost/accumulators/framework/accumulators/value_accumulator.hpp
index 02bf7f3499..148549b085 100644
--- a/boost/accumulators/framework/accumulators/value_accumulator.hpp
+++ b/boost/accumulators/framework/accumulators/value_accumulator.hpp
@@ -30,7 +30,7 @@ namespace impl
template<typename Args>
value_accumulator_impl(Args const &args)
- : val(args[parameter::keyword<Tag>::get()])
+ : val(args[parameter::keyword<Tag>::instance])
{
}
diff --git a/boost/accumulators/framework/depends_on.hpp b/boost/accumulators/framework/depends_on.hpp
index 008f1217da..dd2b637b5c 100644
--- a/boost/accumulators/framework/depends_on.hpp
+++ b/boost/accumulators/framework/depends_on.hpp
@@ -266,11 +266,18 @@ namespace boost { namespace accumulators
template<typename Sequence, typename Args>
typename meta::make_acc_list<Sequence>::type
- make_acc_list(Sequence const &seq, Args const &args)
+ make_acc_list(Sequence &seq, Args const &args)
{
return meta::make_acc_list<Sequence>::call(args, fusion::begin(seq), fusion::end(seq));
}
+ template<typename Sequence, typename Args>
+ typename meta::make_acc_list<Sequence>::type
+ make_acc_list(Sequence const &seq, Args const &args)
+ {
+ return meta::make_acc_list<Sequence const>::call(args, fusion::begin(seq), fusion::end(seq));
+ }
+
///////////////////////////////////////////////////////////////////////////
// checked_as_weighted_feature
template<typename Feature>
diff --git a/boost/accumulators/framework/extractor.hpp b/boost/accumulators/framework/extractor.hpp
index 98281cecb9..169794461c 100644
--- a/boost/accumulators/framework/extractor.hpp
+++ b/boost/accumulators/framework/extractor.hpp
@@ -8,6 +8,7 @@
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005
#define BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005
+#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/tuple/rem.hpp>
#include <boost/preprocessor/array/size.hpp>
#include <boost/preprocessor/array/data.hpp>
@@ -15,11 +16,17 @@
#include <boost/preprocessor/seq/to_array.hpp>
#include <boost/preprocessor/seq/transform.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/parameter/binding.hpp>
-#include <boost/mpl/apply.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/apply.hpp>
+#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/accumulators/accumulators_fwd.hpp>
#include <boost/accumulators/framework/parameters/accumulator.hpp>
@@ -33,14 +40,24 @@ namespace detail
struct accumulator_set_result
{
typedef typename as_feature<Feature>::type feature_type;
- typedef typename mpl::apply<AccumulatorSet, feature_type>::type::result_type type;
+ typedef typename mpl::apply<
+ typename boost::remove_const<
+ typename boost::remove_reference<AccumulatorSet>::type
+ >::type
+ , feature_type
+ >::type::result_type type;
};
template<typename Args, typename Feature>
struct argument_pack_result
: accumulator_set_result<
- typename remove_reference<
- typename parameter::binding<Args, tag::accumulator>::type
+ typename boost::remove_reference<
+ typename parameter::binding<
+ typename boost::remove_const<
+ typename boost::remove_reference<Args>::type
+ >::type
+ , tag::accumulator
+ >::type
>::type
, Feature
>
@@ -147,6 +164,8 @@ struct extractor
, _
)
+#undef BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP
+
#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
/// \overload
///
@@ -156,6 +175,8 @@ struct extractor
#endif
};
+}} // namespace boost::accumulators
+
/// INTERNAL ONLY
///
#define BOOST_ACCUMULATORS_ARRAY_REM(Array) \
@@ -224,6 +245,4 @@ struct extractor
, (3, (Tag, Feature, ParamSeq)) \
)
-}} // namespace boost::accumulators
-
#endif
diff --git a/boost/accumulators/framework/parameters/accumulator.hpp b/boost/accumulators/framework/parameters/accumulator.hpp
index 525ebb30ba..675a3a3924 100644
--- a/boost/accumulators/framework/parameters/accumulator.hpp
+++ b/boost/accumulators/framework/parameters/accumulator.hpp
@@ -8,13 +8,13 @@
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_ACCUMULATOR_HPP_EAN_31_10_2005
#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_ACCUMULATOR_HPP_EAN_31_10_2005
-#include <boost/parameter/keyword.hpp>
+#include <boost/parameter/name.hpp>
#include <boost/accumulators/accumulators_fwd.hpp>
namespace boost { namespace accumulators
{
-BOOST_PARAMETER_KEYWORD(tag, accumulator)
+BOOST_PARAMETER_NAME((accumulator, tag) accumulator)
BOOST_ACCUMULATORS_IGNORE_GLOBAL(accumulator)
}} // namespace boost::accumulators
diff --git a/boost/accumulators/framework/parameters/sample.hpp b/boost/accumulators/framework/parameters/sample.hpp
index 8b227eb334..39afe2b170 100644
--- a/boost/accumulators/framework/parameters/sample.hpp
+++ b/boost/accumulators/framework/parameters/sample.hpp
@@ -8,13 +8,13 @@
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_SAMPLE_HPP_EAN_31_10_2005
#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_SAMPLE_HPP_EAN_31_10_2005
-#include <boost/parameter/keyword.hpp>
+#include <boost/parameter/name.hpp>
#include <boost/accumulators/accumulators_fwd.hpp>
namespace boost { namespace accumulators
{
-BOOST_PARAMETER_KEYWORD(tag, sample)
+BOOST_PARAMETER_NAME((sample, tag) sample)
BOOST_ACCUMULATORS_IGNORE_GLOBAL(sample)
}} // namespace boost::accumulators
diff --git a/boost/accumulators/framework/parameters/weight.hpp b/boost/accumulators/framework/parameters/weight.hpp
index f36016f372..e9c26bfbd0 100644
--- a/boost/accumulators/framework/parameters/weight.hpp
+++ b/boost/accumulators/framework/parameters/weight.hpp
@@ -8,14 +8,14 @@
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHT_HPP_EAN_31_10_2005
#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHT_HPP_EAN_31_10_2005
-#include <boost/parameter/keyword.hpp>
+#include <boost/parameter/name.hpp>
#include <boost/accumulators/accumulators_fwd.hpp>
namespace boost { namespace accumulators
{
// The weight of a single sample
-BOOST_PARAMETER_KEYWORD(tag, weight)
+BOOST_PARAMETER_NAME((weight, tag) weight)
BOOST_ACCUMULATORS_IGNORE_GLOBAL(weight)
}} // namespace boost::accumulators
diff --git a/boost/accumulators/framework/parameters/weights.hpp b/boost/accumulators/framework/parameters/weights.hpp
index 6beae61386..ab1948a86b 100644
--- a/boost/accumulators/framework/parameters/weights.hpp
+++ b/boost/accumulators/framework/parameters/weights.hpp
@@ -8,14 +8,14 @@
#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHTS_HPP_EAN_28_10_2005
#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHTS_HPP_EAN_28_10_2005
-#include <boost/parameter/keyword.hpp>
+#include <boost/parameter/name.hpp>
#include <boost/accumulators/accumulators_fwd.hpp>
namespace boost { namespace accumulators
{
// The weight accumulator
-BOOST_PARAMETER_KEYWORD(tag, weights)
+BOOST_PARAMETER_NAME((weights, tag) weights)
BOOST_ACCUMULATORS_IGNORE_GLOBAL(weights)
}} // namespace boost::accumulators
diff --git a/boost/accumulators/statistics/count.hpp b/boost/accumulators/statistics/count.hpp
index 6d30b41e26..b83435a30e 100644
--- a/boost/accumulators/statistics/count.hpp
+++ b/boost/accumulators/statistics/count.hpp
@@ -43,6 +43,13 @@ namespace impl
return this->cnt;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & cnt;
+ }
+
private:
std::size_t cnt;
};
diff --git a/boost/accumulators/statistics/covariance.hpp b/boost/accumulators/statistics/covariance.hpp
index b3030b9676..d80a85eda7 100644
--- a/boost/accumulators/statistics/covariance.hpp
+++ b/boost/accumulators/statistics/covariance.hpp
@@ -152,6 +152,13 @@ namespace impl
return this->cov_;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & cov_;
+ }
+
private:
result_type cov_;
};
diff --git a/boost/accumulators/statistics/density.hpp b/boost/accumulators/statistics/density.hpp
index 88ca17df79..32b48060fc 100644
--- a/boost/accumulators/statistics/density.hpp
+++ b/boost/accumulators/statistics/density.hpp
@@ -25,6 +25,8 @@
#include <boost/accumulators/statistics/count.hpp>
#include <boost/accumulators/statistics/max.hpp>
#include <boost/accumulators/statistics/min.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/utility.hpp>
namespace boost { namespace accumulators
{
@@ -184,6 +186,20 @@ namespace impl
return make_iterator_range(this->histogram);
}
+ // make this accumulator serializeable
+ // TODO split to save/load and check on parameters provided in ctor
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & cache_size;
+ ar & cache;
+ ar & num_bins;
+ ar & samples_in_bin;
+ ar & bin_positions;
+ ar & histogram;
+ ar & is_dirty;
+ }
+
private:
std::size_t cache_size; // number of cached samples
array_type cache; // cache to store the first cache_size samples
diff --git a/boost/accumulators/statistics/extended_p_square.hpp b/boost/accumulators/statistics/extended_p_square.hpp
index e6cc8dc9a1..6990050e4f 100644
--- a/boost/accumulators/statistics/extended_p_square.hpp
+++ b/boost/accumulators/statistics/extended_p_square.hpp
@@ -26,6 +26,7 @@
#include <boost/accumulators/statistics_fwd.hpp>
#include <boost/accumulators/statistics/count.hpp>
#include <boost/accumulators/statistics/times2_iterator.hpp>
+#include <boost/serialization/vector.hpp>
namespace boost { namespace accumulators
{
@@ -236,6 +237,19 @@ namespace impl
);
}
+ public:
+ // make this accumulator serializeable
+ // TODO: do we need to split to load/save and verify that the parameters did not change?
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & probabilities;
+ ar & heights;
+ ar & actual_positions;
+ ar & desired_positions;
+ ar & positions_increments;
+ }
+
private:
array_type probabilities; // the quantile probabilities
array_type heights; // q_i
diff --git a/boost/accumulators/statistics/extended_p_square_quantile.hpp b/boost/accumulators/statistics/extended_p_square_quantile.hpp
index a17843d774..f57304cd04 100644
--- a/boost/accumulators/statistics/extended_p_square_quantile.hpp
+++ b/boost/accumulators/statistics/extended_p_square_quantile.hpp
@@ -185,6 +185,17 @@ namespace impl
}
}
+
+ public:
+ // make this accumulator serializeable
+ // TODO: do we need to split to load/save and verify that the parameters did not change?
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & probabilities;
+ ar & probability;
+ }
+
private:
array_type probabilities;
diff --git a/boost/accumulators/statistics/kurtosis.hpp b/boost/accumulators/statistics/kurtosis.hpp
index 76c93d3850..9ff9ecdccb 100644
--- a/boost/accumulators/statistics/kurtosis.hpp
+++ b/boost/accumulators/statistics/kurtosis.hpp
@@ -63,6 +63,10 @@ namespace impl
* ( accumulators::moment<2>(args) - mean(args) * mean(args) )
) - 3.;
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
} // namespace impl
diff --git a/boost/accumulators/statistics/max.hpp b/boost/accumulators/statistics/max.hpp
index 820f6593f0..15033e6daa 100644
--- a/boost/accumulators/statistics/max.hpp
+++ b/boost/accumulators/statistics/max.hpp
@@ -48,6 +48,13 @@ namespace impl
return this->max_;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & max_;
+ }
+
private:
Sample max_;
};
diff --git a/boost/accumulators/statistics/mean.hpp b/boost/accumulators/statistics/mean.hpp
index 4788837184..c6df176b78 100644
--- a/boost/accumulators/statistics/mean.hpp
+++ b/boost/accumulators/statistics/mean.hpp
@@ -41,6 +41,10 @@ namespace impl
extractor<SumFeature> sum;
return numeric::fdiv(sum(args), count(args));
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
template<typename Sample, typename Tag>
@@ -71,6 +75,12 @@ namespace impl
return this->mean;
}
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & mean;
+ }
+
private:
result_type mean;
};
diff --git a/boost/accumulators/statistics/median.hpp b/boost/accumulators/statistics/median.hpp
index d361c6dda4..4d4118d8b4 100644
--- a/boost/accumulators/statistics/median.hpp
+++ b/boost/accumulators/statistics/median.hpp
@@ -48,6 +48,10 @@ namespace impl
{
return p_square_quantile_for_median(args);
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
///////////////////////////////////////////////////////////////////////////////
// with_density_median_impl
@@ -105,6 +109,16 @@ namespace impl
return this->median;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & sum;
+ ar & is_dirty;
+ ar & median;
+ }
+
+
private:
mutable float_type sum;
mutable bool is_dirty;
@@ -160,6 +174,15 @@ namespace impl
return this->median;
}
+
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & is_dirty;
+ ar & median;
+ }
+
private:
mutable bool is_dirty;
diff --git a/boost/accumulators/statistics/min.hpp b/boost/accumulators/statistics/min.hpp
index 83943bdb3c..bf30b79e34 100644
--- a/boost/accumulators/statistics/min.hpp
+++ b/boost/accumulators/statistics/min.hpp
@@ -48,6 +48,13 @@ namespace impl
return this->min_;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & min_;
+ }
+
private:
Sample min_;
};
diff --git a/boost/accumulators/statistics/moment.hpp b/boost/accumulators/statistics/moment.hpp
index 3dabd47ecf..9ba1e4caaf 100644
--- a/boost/accumulators/statistics/moment.hpp
+++ b/boost/accumulators/statistics/moment.hpp
@@ -75,6 +75,13 @@ namespace impl
return numeric::fdiv(this->sum, count(args));
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & sum;
+ }
+
private:
Sample sum;
};
diff --git a/boost/accumulators/statistics/p_square_cumul_dist.hpp b/boost/accumulators/statistics/p_square_cumul_dist.hpp
index 50692838c7..daa66f9bd1 100644
--- a/boost/accumulators/statistics/p_square_cumul_dist.hpp
+++ b/boost/accumulators/statistics/p_square_cumul_dist.hpp
@@ -20,6 +20,8 @@
#include <boost/accumulators/framework/parameters/sample.hpp>
#include <boost/accumulators/statistics_fwd.hpp>
#include <boost/accumulators/statistics/count.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/utility.hpp>
namespace boost { namespace accumulators
{
@@ -204,6 +206,20 @@ namespace impl
//return histogram;
return make_iterator_range(this->histogram);
}
+
+ // make this accumulator serializeable
+ // TODO split to save/load and check on parameters provided in ctor
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & num_cells;
+ ar & heights;
+ ar & actual_positions;
+ ar & desired_positions;
+ ar & positions_increments;
+ ar & histogram;
+ ar & is_dirty;
+ }
private:
std::size_t num_cells; // number of cells b
diff --git a/boost/accumulators/statistics/p_square_quantile.hpp b/boost/accumulators/statistics/p_square_quantile.hpp
index 636fea7f23..d87c1b3dbe 100644
--- a/boost/accumulators/statistics/p_square_quantile.hpp
+++ b/boost/accumulators/statistics/p_square_quantile.hpp
@@ -22,6 +22,7 @@
#include <boost/accumulators/statistics_fwd.hpp>
#include <boost/accumulators/statistics/count.hpp>
#include <boost/accumulators/statistics/parameters/quantile_probability.hpp>
+#include <boost/serialization/boost_array.hpp>
namespace boost { namespace accumulators
{
@@ -61,7 +62,7 @@ namespace impl
template<typename Args>
p_square_quantile_impl(Args const &args)
- : p(is_same<Impl, for_median>::value ? 0.5 : args[quantile_probability | 0.5])
+ : p(is_same<Impl, for_median>::value ? float_type(0.5) : args[quantile_probability | float_type(0.5)])
, heights()
, actual_positions()
, desired_positions()
@@ -69,20 +70,21 @@ namespace impl
{
for(std::size_t i = 0; i < 5; ++i)
{
- this->actual_positions[i] = i + 1.;
+ this->actual_positions[i] = i + float_type(1.);
}
- this->desired_positions[0] = 1.;
- this->desired_positions[1] = 1. + 2. * this->p;
- this->desired_positions[2] = 1. + 4. * this->p;
- this->desired_positions[3] = 3. + 2. * this->p;
- this->desired_positions[4] = 5.;
+ this->desired_positions[0] = float_type(1.);
+ this->desired_positions[1] = float_type(1.) + float_type(2.) * this->p;
+ this->desired_positions[2] = float_type(1.) + float_type(4.) * this->p;
+ this->desired_positions[3] = float_type(3.) + float_type(2.) * this->p;
+ this->desired_positions[4] = float_type(5.);
- this->positions_increments[0] = 0.;
- this->positions_increments[1] = this->p / 2.;
+
+ this->positions_increments[0] = float_type(0.);
+ this->positions_increments[1] = this->p / float_type(2.);
this->positions_increments[2] = this->p;
- this->positions_increments[3] = (1. + this->p) / 2.;
- this->positions_increments[4] = 1.;
+ this->positions_increments[3] = (float_type(1.) + this->p) / float_type(2.);
+ this->positions_increments[4] = float_type(1.);
}
template<typename Args>
@@ -156,7 +158,7 @@ namespace impl
float_type hp = (this->heights[i + 1] - this->heights[i]) / dp;
float_type hm = (this->heights[i - 1] - this->heights[i]) / dm;
- if((d >= 1. && dp > 1.) || (d <= -1. && dm < -1.))
+ if((d >= float_type(1.) && dp > float_type(1.)) || (d <= float_type(-1.) && dm < float_type(-1.)))
{
short sign_d = static_cast<short>(d / std::abs(d));
@@ -171,11 +173,11 @@ namespace impl
else
{
// use linear formula
- if(d > 0)
+ if(d > float_type(0))
{
this->heights[i] += hp;
}
- if(d < 0)
+ if(d < float_type(0))
{
this->heights[i] -= hm;
}
@@ -191,6 +193,18 @@ namespace impl
return this->heights[2];
}
+ // make this accumulator serializeable
+ // TODO: do we need to split to load/save and verify that P did not change?
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & p;
+ ar & heights;
+ ar & actual_positions;
+ ar & desired_positions;
+ ar & positions_increments;
+ }
+
private:
float_type p; // the quantile probability p
array_type heights; // q_i
diff --git a/boost/accumulators/statistics/peaks_over_threshold.hpp b/boost/accumulators/statistics/peaks_over_threshold.hpp
index f04f743a0c..de73c658aa 100644
--- a/boost/accumulators/statistics/peaks_over_threshold.hpp
+++ b/boost/accumulators/statistics/peaks_over_threshold.hpp
@@ -181,6 +181,21 @@ namespace impl
return this->fit_parameters_;
}
+ // make this accumulator serializeable
+ // TODO: do we need to split to load/save and verify that threshold did not change?
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & Nu_;
+ ar & mu_;
+ ar & sigma2_;
+ ar & threshold_;
+ ar & get<0>(fit_parameters_);
+ ar & get<1>(fit_parameters_);
+ ar & get<2>(fit_parameters_);
+ ar & is_dirty_;
+ }
+
private:
std::size_t Nu_; // number of samples larger than threshold
mutable float_type mu_; // mean of Nu_ largest samples
@@ -291,6 +306,20 @@ namespace impl
return this->fit_parameters_;
}
+ // make this accumulator serializeable
+ // TODO: do we need to split to load/save and verify that threshold did not change?
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & mu_;
+ ar & sigma2_;
+ ar & threshold_probability_;
+ ar & get<0>(fit_parameters_);
+ ar & get<1>(fit_parameters_);
+ ar & get<2>(fit_parameters_);
+ ar & is_dirty_;
+ }
+
private:
mutable float_type mu_; // mean of samples above threshold u
mutable float_type sigma2_; // variance of samples above threshold u
diff --git a/boost/accumulators/statistics/pot_quantile.hpp b/boost/accumulators/statistics/pot_quantile.hpp
index 470bdbace3..ecd49f2cb2 100644
--- a/boost/accumulators/statistics/pot_quantile.hpp
+++ b/boost/accumulators/statistics/pot_quantile.hpp
@@ -80,6 +80,13 @@ namespace impl
, -xi_hat
) - 1.));
}
+
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & sign_;
+ }
private:
short sign_; // if the fit parameters from the mirrored left tail extreme values are used, mirror back the result
diff --git a/boost/accumulators/statistics/pot_tail_mean.hpp b/boost/accumulators/statistics/pot_tail_mean.hpp
index a78043fce2..96f4dc1f27 100644
--- a/boost/accumulators/statistics/pot_tail_mean.hpp
+++ b/boost/accumulators/statistics/pot_tail_mean.hpp
@@ -90,6 +90,14 @@ namespace impl
is_same<LeftRight, left>::value ? args[quantile_probability] : 1. - args[quantile_probability]
, -xi_hat);
}
+
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & sign_;
+ }
+
private:
short sign_; // if the fit parameters from the mirrored left tail extreme values are used, mirror back the result
};
diff --git a/boost/accumulators/statistics/rolling_count.hpp b/boost/accumulators/statistics/rolling_count.hpp
index 1e34f76354..803f1b7754 100644
--- a/boost/accumulators/statistics/rolling_count.hpp
+++ b/boost/accumulators/statistics/rolling_count.hpp
@@ -40,6 +40,10 @@ namespace impl
{
return static_cast<std::size_t>(rolling_window_plus1(args).size()) - is_rolling_window_plus1_full(args);
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
} // namespace impl
diff --git a/boost/accumulators/statistics/rolling_mean.hpp b/boost/accumulators/statistics/rolling_mean.hpp
index 1439da1e2c..bd5494c3e1 100644
--- a/boost/accumulators/statistics/rolling_mean.hpp
+++ b/boost/accumulators/statistics/rolling_mean.hpp
@@ -43,6 +43,10 @@ namespace boost { namespace accumulators
{
return numeric::fdiv(rolling_sum(args), rolling_count(args));
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
///////////////////////////////////////////////////////////////////////////////
@@ -67,12 +71,18 @@ namespace boost { namespace accumulators
{
if(is_rolling_window_plus1_full(args))
{
- mean_ += numeric::fdiv(args[sample]-rolling_window_plus1(args).front(),rolling_count(args));
+ if (rolling_window_plus1(args).front() > args[sample])
+ mean_ -= numeric::fdiv(rolling_window_plus1(args).front()-args[sample],rolling_count(args));
+ else if (rolling_window_plus1(args).front() < args[sample])
+ mean_ += numeric::fdiv(args[sample]-rolling_window_plus1(args).front(),rolling_count(args));
}
else
{
result_type prev_mean = mean_;
- mean_ += numeric::fdiv(args[sample]-prev_mean,rolling_count(args));
+ if (prev_mean > args[sample])
+ mean_ -= numeric::fdiv(prev_mean-args[sample],rolling_count(args));
+ else if (prev_mean < args[sample])
+ mean_ += numeric::fdiv(args[sample]-prev_mean,rolling_count(args));
}
}
@@ -81,6 +91,13 @@ namespace boost { namespace accumulators
{
return mean_;
}
+
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & mean_;
+ }
private:
@@ -176,4 +193,4 @@ namespace boost { namespace accumulators
};
}} // namespace boost::accumulators
-#endif \ No newline at end of file
+#endif
diff --git a/boost/accumulators/statistics/rolling_moment.hpp b/boost/accumulators/statistics/rolling_moment.hpp
index f172cee34f..28ea5b580a 100644
--- a/boost/accumulators/statistics/rolling_moment.hpp
+++ b/boost/accumulators/statistics/rolling_moment.hpp
@@ -58,6 +58,13 @@ namespace impl
return numeric::fdiv(this->sum_, rolling_count(args));
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & sum_;
+ }
+
private:
result_type sum_;
};
diff --git a/boost/accumulators/statistics/rolling_sum.hpp b/boost/accumulators/statistics/rolling_sum.hpp
index bbb7a8e9a0..c511460655 100644
--- a/boost/accumulators/statistics/rolling_sum.hpp
+++ b/boost/accumulators/statistics/rolling_sum.hpp
@@ -51,6 +51,13 @@ namespace impl
return this->sum_;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & sum_;
+ }
+
private:
Sample sum_;
};
diff --git a/boost/accumulators/statistics/rolling_variance.hpp b/boost/accumulators/statistics/rolling_variance.hpp
index 33b3922a50..249d5c1996 100644
--- a/boost/accumulators/statistics/rolling_variance.hpp
+++ b/boost/accumulators/statistics/rolling_variance.hpp
@@ -62,6 +62,10 @@ namespace impl
if (nr_samples < 2) return result_type();
return nr_samples*(rolling_moment<2>(args) - mean*mean)/(nr_samples-1);
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
//! Iterative calculation of the rolling variance.
@@ -138,6 +142,14 @@ namespace impl
if (nr_samples < 2) return result_type();
return numeric::fdiv(sum_of_squares_,(nr_samples-1));
}
+
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & previous_mean_;
+ ar & sum_of_squares_;
+ }
private:
diff --git a/boost/accumulators/statistics/rolling_window.hpp b/boost/accumulators/statistics/rolling_window.hpp
index 2e0a33420a..a43ecdfdac 100644
--- a/boost/accumulators/statistics/rolling_window.hpp
+++ b/boost/accumulators/statistics/rolling_window.hpp
@@ -21,6 +21,45 @@
#include <boost/accumulators/framework/parameters/accumulator.hpp>
#include <boost/accumulators/numeric/functional.hpp>
#include <boost/accumulators/statistics_fwd.hpp>
+#include <boost/serialization/split_free.hpp>
+
+namespace boost { namespace serialization {
+
+// implement serialization for boost::circular_buffer
+template <class Archive, class T>
+void save(Archive& ar, const circular_buffer<T>& b, const unsigned int /* version */)
+{
+ typename circular_buffer<T>::size_type size = b.size();
+ ar << b.capacity();
+ ar << size;
+ const typename circular_buffer<T>::const_array_range one = b.array_one();
+ const typename circular_buffer<T>::const_array_range two = b.array_two();
+ ar.save_binary(one.first, one.second*sizeof(T));
+ ar.save_binary(two.first, two.second*sizeof(T));
+}
+
+template <class Archive, class T>
+void load(Archive& ar, circular_buffer<T>& b, const unsigned int /* version */)
+{
+ typename circular_buffer<T>::capacity_type capacity;
+ typename circular_buffer<T>::size_type size;
+ ar >> capacity;
+ b.set_capacity(capacity);
+ ar >> size;
+ b.clear();
+ const typename circular_buffer<T>::pointer buff = new T[size*sizeof(T)];
+ ar.load_binary(buff, size*sizeof(T));
+ b.insert(b.begin(), buff, buff+size);
+ delete[] buff;
+}
+
+template<class Archive, class T>
+inline void serialize(Archive & ar, circular_buffer<T>& b, const unsigned int version)
+{
+ split_free(ar, b, version);
+}
+
+} } // end namespace boost::serialization
namespace boost { namespace accumulators
{
@@ -83,6 +122,12 @@ namespace impl
return result_type(this->buffer_.begin(), this->buffer_.end());
}
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar & buffer_;
+ }
+
private:
circular_buffer<Sample> buffer_;
};
@@ -112,6 +157,10 @@ namespace impl
{
return rolling_window_plus1(args).advance_begin(is_rolling_window_plus1_full(args));
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
} // namespace impl
diff --git a/boost/accumulators/statistics/skewness.hpp b/boost/accumulators/statistics/skewness.hpp
index c383ec4a6c..9c9c376a8a 100644
--- a/boost/accumulators/statistics/skewness.hpp
+++ b/boost/accumulators/statistics/skewness.hpp
@@ -65,6 +65,10 @@ namespace impl
* std::sqrt( accumulators::moment<2>(args) - mean(args) * mean(args) )
);
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
} // namespace impl
diff --git a/boost/accumulators/statistics/sum.hpp b/boost/accumulators/statistics/sum.hpp
index 126ce244fd..7e507ccc26 100644
--- a/boost/accumulators/statistics/sum.hpp
+++ b/boost/accumulators/statistics/sum.hpp
@@ -51,8 +51,13 @@ namespace impl
return this->sum;
}
- private:
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & sum;
+ }
+ private:
Sample sum;
};
diff --git a/boost/accumulators/statistics/sum_kahan.hpp b/boost/accumulators/statistics/sum_kahan.hpp
index 97ade18da8..b5e9092238 100644
--- a/boost/accumulators/statistics/sum_kahan.hpp
+++ b/boost/accumulators/statistics/sum_kahan.hpp
@@ -66,6 +66,14 @@ struct sum_kahan_impl
return this->sum;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & sum;
+ ar & compensation;
+ }
+
private:
Sample sum;
Sample compensation;
diff --git a/boost/accumulators/statistics/tail.hpp b/boost/accumulators/statistics/tail.hpp
index be6cdee392..154a30cc26 100644
--- a/boost/accumulators/statistics/tail.hpp
+++ b/boost/accumulators/statistics/tail.hpp
@@ -268,6 +268,17 @@ namespace impl
std::vector<Sample> const &samples;
};
+ public:
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & is_sorted;
+ ar & indices;
+ ar & samples;
+ }
+
+ private:
mutable bool is_sorted;
mutable std::vector<std::size_t> indices;
std::vector<Sample> samples;
diff --git a/boost/accumulators/statistics/tail_mean.hpp b/boost/accumulators/statistics/tail_mean.hpp
index 67dae37b50..f56606d14e 100644
--- a/boost/accumulators/statistics/tail_mean.hpp
+++ b/boost/accumulators/statistics/tail_mean.hpp
@@ -88,6 +88,10 @@ namespace impl
- numeric::fdiv(n, count(args))
);
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
///////////////////////////////////////////////////////////////////////////////
@@ -159,6 +163,10 @@ namespace impl
}
}
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
} // namespace impl
diff --git a/boost/accumulators/statistics/tail_quantile.hpp b/boost/accumulators/statistics/tail_quantile.hpp
index 9ff56b56e5..ed1f6e6dff 100644
--- a/boost/accumulators/statistics/tail_quantile.hpp
+++ b/boost/accumulators/statistics/tail_quantile.hpp
@@ -98,6 +98,10 @@ namespace impl
}
}
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
} // namespace impl
diff --git a/boost/accumulators/statistics/tail_variate.hpp b/boost/accumulators/statistics/tail_variate.hpp
index a9fc7d297a..6885ece15f 100644
--- a/boost/accumulators/statistics/tail_variate.hpp
+++ b/boost/accumulators/statistics/tail_variate.hpp
@@ -18,6 +18,7 @@
#include <boost/accumulators/framework/depends_on.hpp>
#include <boost/accumulators/statistics_fwd.hpp>
#include <boost/accumulators/statistics/tail.hpp>
+#include <boost/serialization/vector.hpp>
namespace boost { namespace accumulators
{
@@ -69,6 +70,14 @@ namespace impl
);
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & variates;
+ }
+
+ private:
std::vector<VariateType> variates;
};
diff --git a/boost/accumulators/statistics/tail_variate_means.hpp b/boost/accumulators/statistics/tail_variate_means.hpp
index a97eab5648..efe9f7c37e 100644
--- a/boost/accumulators/statistics/tail_variate_means.hpp
+++ b/boost/accumulators/statistics/tail_variate_means.hpp
@@ -27,6 +27,7 @@
#include <boost/accumulators/statistics/tail_variate.hpp>
#include <boost/accumulators/statistics/tail_mean.hpp>
#include <boost/accumulators/statistics/parameters/quantile_probability.hpp>
+#include <boost/serialization/vector.hpp>
#ifdef _MSC_VER
# pragma warning(push)
@@ -145,6 +146,13 @@ namespace impl
return make_iterator_range(this->tail_means_);
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & tail_means_;
+ }
+
private:
mutable array_type tail_means_;
diff --git a/boost/accumulators/statistics/variance.hpp b/boost/accumulators/statistics/variance.hpp
index baac55696b..9db858d2fb 100644
--- a/boost/accumulators/statistics/variance.hpp
+++ b/boost/accumulators/statistics/variance.hpp
@@ -53,6 +53,10 @@ namespace impl
result_type tmp = mean(args);
return accumulators::moment<2>(args) - tmp * tmp;
}
+
+ // serialization is done by accumulators it depends on
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version) {}
};
//! Iterative calculation of variance.
@@ -113,6 +117,13 @@ namespace impl
return this->variance;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & variance;
+ }
+
private:
result_type variance;
};
diff --git a/boost/accumulators/statistics/weighted_covariance.hpp b/boost/accumulators/statistics/weighted_covariance.hpp
index 25d613c120..e423a225a9 100644
--- a/boost/accumulators/statistics/weighted_covariance.hpp
+++ b/boost/accumulators/statistics/weighted_covariance.hpp
@@ -97,6 +97,13 @@ namespace impl
return this->cov_;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & cov_;
+ }
+
private:
result_type cov_;
};
diff --git a/boost/accumulators/statistics/weighted_density.hpp b/boost/accumulators/statistics/weighted_density.hpp
index 1407368016..6b5a0ee015 100644
--- a/boost/accumulators/statistics/weighted_density.hpp
+++ b/boost/accumulators/statistics/weighted_density.hpp
@@ -23,6 +23,8 @@
#include <boost/accumulators/statistics/max.hpp>
#include <boost/accumulators/statistics/min.hpp>
#include <boost/accumulators/statistics/density.hpp> // for named parameters density_cache_size and density_num_bins
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/utility.hpp>
namespace boost { namespace accumulators
{
@@ -171,6 +173,20 @@ namespace impl
return make_iterator_range(this->histogram);
}
+ // make this accumulator serializeable
+ // TODO split to save/load and check on parameters provided in ctor
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & cache_size;
+ ar & cache;
+ ar & num_bins;
+ ar & samples_in_bin;
+ ar & bin_positions;
+ ar & histogram;
+ ar & is_dirty;
+ }
+
private:
std::size_t cache_size; // number of cached samples
histogram_type cache; // cache to store the first cache_size samples with their weights as std::pair
diff --git a/boost/accumulators/statistics/weighted_extended_p_square.hpp b/boost/accumulators/statistics/weighted_extended_p_square.hpp
index ac857e056d..f88e9b9ee8 100644
--- a/boost/accumulators/statistics/weighted_extended_p_square.hpp
+++ b/boost/accumulators/statistics/weighted_extended_p_square.hpp
@@ -28,6 +28,7 @@
#include <boost/accumulators/statistics/sum.hpp>
#include <boost/accumulators/statistics/times2_iterator.hpp>
#include <boost/accumulators/statistics/extended_p_square.hpp>
+#include <boost/serialization/vector.hpp>
namespace boost { namespace accumulators
{
@@ -251,6 +252,17 @@ namespace impl
);
}
+ // make this accumulator serializeable
+ // TODO: do we need to split to load/save and verify that the parameters did not change?
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & probabilities;
+ ar & heights;
+ ar & actual_positions;
+ ar & desired_positions;
+ }
+
private:
array_type probabilities; // the quantile probabilities
array_type heights; // q_i
diff --git a/boost/accumulators/statistics/weighted_mean.hpp b/boost/accumulators/statistics/weighted_mean.hpp
index a80ef0984c..1ddce8dd57 100644
--- a/boost/accumulators/statistics/weighted_mean.hpp
+++ b/boost/accumulators/statistics/weighted_mean.hpp
@@ -97,6 +97,13 @@ namespace impl
return this->mean;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & mean;
+ }
+
private:
result_type mean;
};
diff --git a/boost/accumulators/statistics/weighted_median.hpp b/boost/accumulators/statistics/weighted_median.hpp
index ed7cadb331..22224a877a 100644
--- a/boost/accumulators/statistics/weighted_median.hpp
+++ b/boost/accumulators/statistics/weighted_median.hpp
@@ -106,6 +106,15 @@ namespace impl
return this->median;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & sum;
+ ar & is_dirty;
+ ar & median;
+ }
+
private:
mutable float_type sum;
mutable bool is_dirty;
@@ -162,6 +171,15 @@ namespace impl
return this->median;
}
+
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & is_dirty;
+ ar & median;
+ }
+
private:
mutable bool is_dirty;
mutable float_type median;
diff --git a/boost/accumulators/statistics/weighted_moment.hpp b/boost/accumulators/statistics/weighted_moment.hpp
index 011701c704..5b6129066a 100644
--- a/boost/accumulators/statistics/weighted_moment.hpp
+++ b/boost/accumulators/statistics/weighted_moment.hpp
@@ -60,6 +60,13 @@ namespace impl
return numeric::fdiv(this->sum, sum_of_weights(args));
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & sum;
+ }
+
private:
weighted_sample sum;
};
diff --git a/boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp b/boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp
index ce750ed1f5..f8a44d605b 100644
--- a/boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp
+++ b/boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp
@@ -221,6 +221,19 @@ namespace impl
return make_iterator_range(this->histogram);
}
+ // make this accumulator serializeable
+ // TODO split to save/load and check on parameters provided in ctor
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & num_cells;
+ ar & heights;
+ ar & actual_positions;
+ ar & desired_positions;
+ ar & histogram;
+ ar & is_dirty;
+ }
+
private:
std::size_t num_cells; // number of cells b
array_type heights; // q_i
diff --git a/boost/accumulators/statistics/weighted_p_square_quantile.hpp b/boost/accumulators/statistics/weighted_p_square_quantile.hpp
index 2ebc7b1845..fecd993911 100644
--- a/boost/accumulators/statistics/weighted_p_square_quantile.hpp
+++ b/boost/accumulators/statistics/weighted_p_square_quantile.hpp
@@ -208,6 +208,17 @@ namespace impl {
return this->heights[2];
}
+ // make this accumulator serializeable
+ // TODO split to save/load and check on parameters provided in ctor
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & p;
+ ar & heights;
+ ar & actual_positions;
+ ar & desired_positions;
+ }
+
private:
float_type p; // the quantile probability p
array_type heights; // q_i
diff --git a/boost/accumulators/statistics/weighted_peaks_over_threshold.hpp b/boost/accumulators/statistics/weighted_peaks_over_threshold.hpp
index 418b38cfe0..f3dc327b9e 100644
--- a/boost/accumulators/statistics/weighted_peaks_over_threshold.hpp
+++ b/boost/accumulators/statistics/weighted_peaks_over_threshold.hpp
@@ -109,6 +109,19 @@ namespace impl
return this->fit_parameters_;
}
+ // make this accumulator serializeable
+ // TODO: do we need to split to load/save and verify that threshold did not change?
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & sign_;
+ ar & mu_;
+ ar & sigma2_;
+ ar & threshold_;
+ ar & fit_parameters_;
+ ar & is_dirty_;
+ }
+
private:
short sign_; // for left tail fitting, mirror the extreme values
mutable float_type mu_; // mean of samples above threshold
diff --git a/boost/accumulators/statistics/weighted_sum.hpp b/boost/accumulators/statistics/weighted_sum.hpp
index 27153906d0..41091f8766 100644
--- a/boost/accumulators/statistics/weighted_sum.hpp
+++ b/boost/accumulators/statistics/weighted_sum.hpp
@@ -55,6 +55,13 @@ namespace impl
return this->weighted_sum_;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & weighted_sum_;
+ }
+
private:
weighted_sample weighted_sum_;
diff --git a/boost/accumulators/statistics/weighted_sum_kahan.hpp b/boost/accumulators/statistics/weighted_sum_kahan.hpp
index fbb0303acc..5ee5250d69 100644
--- a/boost/accumulators/statistics/weighted_sum_kahan.hpp
+++ b/boost/accumulators/statistics/weighted_sum_kahan.hpp
@@ -68,6 +68,14 @@ namespace impl
return this->weighted_sum_;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & weighted_sum_;
+ ar & compensation;
+ }
+
private:
weighted_sample weighted_sum_;
weighted_sample compensation;
diff --git a/boost/accumulators/statistics/weighted_tail_variate_means.hpp b/boost/accumulators/statistics/weighted_tail_variate_means.hpp
index b1133109ed..f096a93b52 100644
--- a/boost/accumulators/statistics/weighted_tail_variate_means.hpp
+++ b/boost/accumulators/statistics/weighted_tail_variate_means.hpp
@@ -179,6 +179,13 @@ namespace impl
return make_iterator_range(this->tail_means_);
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & tail_means_;
+ }
+
private:
mutable array_type tail_means_;
diff --git a/boost/accumulators/statistics/weighted_variance.hpp b/boost/accumulators/statistics/weighted_variance.hpp
index bc199affa4..f7d2b6e5f7 100644
--- a/boost/accumulators/statistics/weighted_variance.hpp
+++ b/boost/accumulators/statistics/weighted_variance.hpp
@@ -103,6 +103,13 @@ namespace impl
return this->weighted_variance;
}
+ // make this accumulator serializeable
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int file_version)
+ {
+ ar & weighted_variance;
+ }
+
private:
result_type weighted_variance;
};
diff --git a/boost/algorithm/find_backward.hpp b/boost/algorithm/find_backward.hpp
index 66901a1471..6102c9ab24 100644
--- a/boost/algorithm/find_backward.hpp
+++ b/boost/algorithm/find_backward.hpp
@@ -2,7 +2,7 @@
Copyright (c) T. Zachary Laine 2018.
Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALGORITHM_FIND_BACKWARD_HPP
#define BOOST_ALGORITHM_FIND_BACKWARD_HPP
diff --git a/boost/algorithm/find_not.hpp b/boost/algorithm/find_not.hpp
index ef4df00b84..4d8a28abf3 100644
--- a/boost/algorithm/find_not.hpp
+++ b/boost/algorithm/find_not.hpp
@@ -2,7 +2,7 @@
Copyright (c) T. Zachary Laine 2018.
Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt)
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALGORITHM_FIND_NOT_HPP
#define BOOST_ALGORITHM_FIND_NOT_HPP
diff --git a/boost/algorithm/string/iter_find.hpp b/boost/algorithm/string/iter_find.hpp
index 10424abc74..d76a819896 100644
--- a/boost/algorithm/string/iter_find.hpp
+++ b/boost/algorithm/string/iter_find.hpp
@@ -71,7 +71,11 @@ namespace boost {
inline SequenceSequenceT&
iter_find(
SequenceSequenceT& Result,
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ RangeT&& Input,
+#else
RangeT& Input,
+#endif
FinderT Finder )
{
BOOST_CONCEPT_ASSERT((
@@ -142,7 +146,11 @@ namespace boost {
inline SequenceSequenceT&
iter_split(
SequenceSequenceT& Result,
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ RangeT&& Input,
+#else
RangeT& Input,
+#endif
FinderT Finder )
{
BOOST_CONCEPT_ASSERT((
diff --git a/boost/algorithm/string/split.hpp b/boost/algorithm/string/split.hpp
index cae712c07f..e0b30fb353 100644
--- a/boost/algorithm/string/split.hpp
+++ b/boost/algorithm/string/split.hpp
@@ -61,7 +61,11 @@ namespace boost {
template< typename SequenceSequenceT, typename Range1T, typename Range2T >
inline SequenceSequenceT& find_all(
SequenceSequenceT& Result,
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ Range1T&& Input,
+#else
Range1T& Input,
+#endif
const Range2T& Search)
{
return ::boost::algorithm::iter_find(
@@ -96,7 +100,11 @@ namespace boost {
template< typename SequenceSequenceT, typename Range1T, typename Range2T >
inline SequenceSequenceT& ifind_all(
SequenceSequenceT& Result,
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ Range1T&& Input,
+#else
Range1T& Input,
+#endif
const Range2T& Search,
const std::locale& Loc=std::locale() )
{
@@ -139,7 +147,11 @@ namespace boost {
template< typename SequenceSequenceT, typename RangeT, typename PredicateT >
inline SequenceSequenceT& split(
SequenceSequenceT& Result,
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ RangeT&& Input,
+#else
RangeT& Input,
+#endif
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off )
{
diff --git a/boost/align/align_down.hpp b/boost/align/align_down.hpp
index 355844f8aa..932598c0fa 100644
--- a/boost/align/align_down.hpp
+++ b/boost/align/align_down.hpp
@@ -9,14 +9,16 @@ Distributed under the Boost Software License, Version 1.0.
#define BOOST_ALIGN_ALIGN_DOWN_HPP
#include <boost/align/detail/align_down.hpp>
+#include <boost/align/detail/not_pointer.hpp>
namespace boost {
namespace alignment {
-BOOST_CONSTEXPR inline std::size_t
-align_down(std::size_t value, std::size_t alignment) BOOST_NOEXCEPT
+template<class T>
+BOOST_CONSTEXPR inline typename detail::not_pointer<T, T>::type
+align_down(T value, std::size_t alignment) BOOST_NOEXCEPT
{
- return value & ~(alignment - 1);
+ return T(value & ~T(alignment - 1));
}
} /* alignment */
diff --git a/boost/align/align_up.hpp b/boost/align/align_up.hpp
index 6401ea848a..84e1a3cb58 100644
--- a/boost/align/align_up.hpp
+++ b/boost/align/align_up.hpp
@@ -9,14 +9,16 @@ Distributed under the Boost Software License, Version 1.0.
#define BOOST_ALIGN_ALIGN_UP_HPP
#include <boost/align/detail/align_up.hpp>
+#include <boost/align/detail/not_pointer.hpp>
namespace boost {
namespace alignment {
-BOOST_CONSTEXPR inline std::size_t
-align_up(std::size_t value, std::size_t alignment) BOOST_NOEXCEPT
+template<class T>
+BOOST_CONSTEXPR inline typename detail::not_pointer<T, T>::type
+align_up(T value, std::size_t alignment) BOOST_NOEXCEPT
{
- return (value + alignment - 1) & ~(alignment - 1);
+ return T((value + (T(alignment) - 1)) & ~T(alignment - 1));
}
} /* alignment */
diff --git a/boost/align/aligned_allocator.hpp b/boost/align/aligned_allocator.hpp
index 4ec6b50c2f..193cd4e696 100644
--- a/boost/align/aligned_allocator.hpp
+++ b/boost/align/aligned_allocator.hpp
@@ -8,15 +8,15 @@ Distributed under the Boost Software License, Version 1.0.
#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_HPP
#define BOOST_ALIGN_ALIGNED_ALLOCATOR_HPP
-#include <boost/align/detail/addressof.hpp>
+#include <boost/align/detail/add_reference.hpp>
#include <boost/align/detail/is_alignment_constant.hpp>
#include <boost/align/detail/max_objects.hpp>
#include <boost/align/detail/max_size.hpp>
+#include <boost/align/detail/throw_exception.hpp>
#include <boost/align/aligned_alloc.hpp>
#include <boost/align/aligned_allocator_forward.hpp>
#include <boost/align/alignment_of.hpp>
#include <boost/static_assert.hpp>
-#include <boost/throw_exception.hpp>
#include <new>
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -36,10 +36,13 @@ public:
typedef const T* const_pointer;
typedef void* void_pointer;
typedef const void* const_void_pointer;
+ typedef typename detail::add_lvalue_reference<T>::type reference;
+ typedef typename detail::add_lvalue_reference<const
+ T>::type const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
- typedef T& reference;
- typedef const T& const_reference;
+ typedef detail::true_type propagate_on_container_move_assignment;
+ typedef detail::true_type is_always_equal;
template<class U>
struct rebind {
@@ -56,14 +59,6 @@ public:
aligned_allocator(const aligned_allocator<U, Alignment>&)
BOOST_NOEXCEPT { }
- pointer address(reference value) const BOOST_NOEXCEPT {
- return detail::addressof(value);
- }
-
- const_pointer address(const_reference value) const BOOST_NOEXCEPT {
- return detail::addressof(value);
- }
-
pointer allocate(size_type size, const_void_pointer = 0) {
enum {
m = detail::max_size<Alignment,
@@ -74,7 +69,7 @@ public:
}
void* p = boost::alignment::aligned_alloc(m, sizeof(T) * size);
if (!p) {
- boost::throw_exception(std::bad_alloc());
+ detail::throw_exception(std::bad_alloc());
}
return static_cast<T*>(p);
}
@@ -104,6 +99,11 @@ public:
void construct(U* ptr, const V& value) {
::new((void*)ptr) U(value);
}
+
+ template<class U, class V>
+ void construct(U* ptr, V& value) {
+ ::new((void*)ptr) U(value);
+ }
#endif
template<class U>
@@ -118,21 +118,6 @@ public:
}
};
-template<std::size_t Alignment>
-class aligned_allocator<void, Alignment> {
- BOOST_STATIC_ASSERT(detail::is_alignment_constant<Alignment>::value);
-
-public:
- typedef void value_type;
- typedef void* pointer;
- typedef const void* const_pointer;
-
- template<class U>
- struct rebind {
- typedef aligned_allocator<U, Alignment> other;
- };
-};
-
template<class T, class U, std::size_t Alignment>
inline bool
operator==(const aligned_allocator<T, Alignment>&,
diff --git a/boost/align/aligned_allocator_adaptor.hpp b/boost/align/aligned_allocator_adaptor.hpp
index 912651687a..d352742ed4 100644
--- a/boost/align/aligned_allocator_adaptor.hpp
+++ b/boost/align/aligned_allocator_adaptor.hpp
@@ -74,12 +74,8 @@ public:
#endif
};
-#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
- aligned_allocator_adaptor() = default;
-#else
aligned_allocator_adaptor()
: Allocator() { }
-#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<class A>
diff --git a/boost/align/alignment_of.hpp b/boost/align/alignment_of.hpp
index 488df0b9e0..cf0f5874f1 100644
--- a/boost/align/alignment_of.hpp
+++ b/boost/align/alignment_of.hpp
@@ -11,7 +11,9 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/align/detail/element_type.hpp>
#include <boost/align/alignment_of_forward.hpp>
-#if defined(BOOST_MSVC)
+#if defined(_MSC_VER) && defined(__clang__)
+#include <boost/align/detail/alignment_of_cxx11.hpp>
+#elif defined(BOOST_MSVC)
#include <boost/align/detail/alignment_of_msvc.hpp>
#elif defined(__GNUC__) && defined(__unix__) && !defined(__LP64__)
#include <boost/align/detail/alignment_of.hpp>
diff --git a/boost/align/detail/add_reference.hpp b/boost/align/detail/add_reference.hpp
new file mode 100644
index 0000000000..9cb7cde589
--- /dev/null
+++ b/boost/align/detail/add_reference.hpp
@@ -0,0 +1,44 @@
+/*
+Copyright 2019 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_ALIGN_DETAIL_ADD_REFERENCE_HPP
+#define BOOST_ALIGN_DETAIL_ADD_REFERENCE_HPP
+
+#include <boost/config.hpp>
+
+#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
+#include <type_traits>
+#endif
+
+namespace boost {
+namespace alignment {
+namespace detail {
+
+#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
+using std::add_lvalue_reference;
+#else
+template<class T>
+struct add_lvalue_reference {
+ typedef T& type;
+};
+
+template<>
+struct add_lvalue_reference<void> {
+ typedef void type;
+};
+
+template<>
+struct add_lvalue_reference<const void> {
+ typedef const void type;
+};
+#endif
+
+} /* detail */
+} /* alignment */
+} /* boost */
+
+#endif
diff --git a/boost/align/detail/addressof.hpp b/boost/align/detail/addressof.hpp
deleted file mode 100644
index a314830bed..0000000000
--- a/boost/align/detail/addressof.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-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)
-*/
-#ifndef BOOST_ALIGN_DETAIL_ADDRESSOF_HPP
-#define BOOST_ALIGN_DETAIL_ADDRESSOF_HPP
-
-#include <boost/config.hpp>
-
-#if !defined(BOOST_NO_CXX11_ADDRESSOF)
-#include <memory>
-#else
-#include <boost/core/addressof.hpp>
-#endif
-
-namespace boost {
-namespace alignment {
-namespace detail {
-
-#if !defined(BOOST_NO_CXX11_ADDRESSOF)
-using std::addressof;
-#else
-using boost::addressof;
-#endif
-
-} /* detail */
-} /* alignment */
-} /* boost */
-
-#endif
diff --git a/boost/align/detail/integral_constant.hpp b/boost/align/detail/integral_constant.hpp
index 860096783e..a1e0b467ab 100644
--- a/boost/align/detail/integral_constant.hpp
+++ b/boost/align/detail/integral_constant.hpp
@@ -20,6 +20,8 @@ namespace detail {
#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
using std::integral_constant;
+using std::true_type;
+using std::false_type;
#else
template<class T, T Value>
struct integral_constant {
@@ -39,6 +41,9 @@ struct integral_constant {
template<class T, T Value>
BOOST_CONSTEXPR_OR_CONST T integral_constant<T, Value>::value;
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
#endif
} /* detail */
diff --git a/boost/align/detail/is_aligned.hpp b/boost/align/detail/is_aligned.hpp
index 61982c4685..27de0bd521 100644
--- a/boost/align/detail/is_aligned.hpp
+++ b/boost/align/detail/is_aligned.hpp
@@ -15,14 +15,14 @@ namespace boost {
namespace alignment {
inline bool
-is_aligned(const void* ptr, std::size_t alignment) BOOST_NOEXCEPT
+is_aligned(const volatile void* ptr, std::size_t alignment) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
return (reinterpret_cast<std::size_t>(ptr) & (alignment - 1)) == 0;
}
inline bool
-is_aligned(std::size_t alignment, const void* ptr) BOOST_NOEXCEPT
+is_aligned(std::size_t alignment, const volatile void* ptr) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
return (reinterpret_cast<std::size_t>(ptr) & (alignment - 1)) == 0;
diff --git a/boost/align/detail/not_pointer.hpp b/boost/align/detail/not_pointer.hpp
new file mode 100644
index 0000000000..122610182b
--- /dev/null
+++ b/boost/align/detail/not_pointer.hpp
@@ -0,0 +1,27 @@
+/*
+Copyright 2019 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_ALIGN_DETAIL_NOT_POINTER_HPP
+#define BOOST_ALIGN_DETAIL_NOT_POINTER_HPP
+
+namespace boost {
+namespace alignment {
+namespace detail {
+
+template<class T, class U>
+struct not_pointer {
+ typedef U type;
+};
+
+template<class T, class U>
+struct not_pointer<T*, U> { };
+
+} /* detail */
+} /* alignment */
+} /* boost */
+
+#endif
diff --git a/boost/align/detail/throw_exception.hpp b/boost/align/detail/throw_exception.hpp
new file mode 100644
index 0000000000..6ae5c137f7
--- /dev/null
+++ b/boost/align/detail/throw_exception.hpp
@@ -0,0 +1,44 @@
+/*
+Copyright 2019 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_ALIGN_DETAIL_THROW_EXCEPTION_HPP
+#define BOOST_ALIGN_DETAIL_THROW_EXCEPTION_HPP
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_EXCEPTIONS)
+#include <exception>
+#endif
+
+namespace boost {
+
+#if defined(BOOST_NO_EXCEPTIONS)
+void throw_exception(const std::exception&);
+#endif
+
+namespace alignment {
+namespace detail {
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+template<class E>
+BOOST_NORETURN inline void
+throw_exception(const E& error)
+{
+ throw error;
+}
+#else
+BOOST_NORETURN inline void
+throw_exception(const std::exception& error)
+{
+ boost::throw_exception(error);
+}
+#endif
+
+} /* detail */
+} /* alignment */
+} /* boost */
+
+#endif
diff --git a/boost/align/is_aligned.hpp b/boost/align/is_aligned.hpp
index c8266d0eae..a661d580f5 100644
--- a/boost/align/is_aligned.hpp
+++ b/boost/align/is_aligned.hpp
@@ -10,14 +10,16 @@ Distributed under the Boost Software License, Version 1.0.
#define BOOST_ALIGN_IS_ALIGNED_HPP
#include <boost/align/detail/is_aligned.hpp>
+#include <boost/align/detail/not_pointer.hpp>
namespace boost {
namespace alignment {
-BOOST_CONSTEXPR inline bool
-is_aligned(std::size_t value, std::size_t alignment) BOOST_NOEXCEPT
+template<class T>
+BOOST_CONSTEXPR inline typename detail::not_pointer<T, bool>::type
+is_aligned(T value, std::size_t alignment) BOOST_NOEXCEPT
{
- return (value & (alignment - 1)) == 0;
+ return (value & (T(alignment) - 1)) == 0;
}
} /* alignment */
diff --git a/boost/any.hpp b/boost/any.hpp
index f161b3ff17..36dd11fecc 100644
--- a/boost/any.hpp
+++ b/boost/any.hpp
@@ -38,7 +38,7 @@ namespace boost
{
public: // structors
- any() BOOST_NOEXCEPT
+ BOOST_CONSTEXPR any() BOOST_NOEXCEPT
: content(0)
{
}
@@ -98,7 +98,7 @@ namespace boost
any & operator=(any rhs)
{
- any(rhs).swap(*this);
+ rhs.swap(*this);
return *this;
}
@@ -166,7 +166,11 @@ namespace boost
};
template<typename ValueType>
- class holder : public placeholder
+ class holder
+#ifndef BOOST_NO_CXX11_FINAL
+ final
+#endif
+ : public placeholder
{
public: // structors
diff --git a/boost/asio/basic_serial_port.hpp b/boost/asio/basic_serial_port.hpp
index 88a195a46a..55144ee5de 100644
--- a/boost/asio/basic_serial_port.hpp
+++ b/boost/asio/basic_serial_port.hpp
@@ -554,7 +554,7 @@ public:
* boost::asio::serial_port_base::character_size
*/
template <typename GettableSerialPortOption>
- void get_option(GettableSerialPortOption& option)
+ void get_option(GettableSerialPortOption& option) const
{
boost::system::error_code ec;
impl_.get_service().get_option(impl_.get_implementation(), option, ec);
@@ -579,7 +579,7 @@ public:
*/
template <typename GettableSerialPortOption>
BOOST_ASIO_SYNC_OP_VOID get_option(GettableSerialPortOption& option,
- boost::system::error_code& ec)
+ boost::system::error_code& ec) const
{
impl_.get_service().get_option(impl_.get_implementation(), option, ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
diff --git a/boost/asio/buffer.hpp b/boost/asio/buffer.hpp
index 6958b2e84a..1f12cac22d 100644
--- a/boost/asio/buffer.hpp
+++ b/boost/asio/buffer.hpp
@@ -2476,7 +2476,7 @@ struct is_dynamic_buffer_v2
* If @c BOOST_ASIO_NO_DYNAMIC_BUFFER_V1 is not defined, determines whether the
* type satisfies the DynamicBuffer_v1 requirements. Otherwise, if @c
* BOOST_ASIO_NO_DYNAMIC_BUFFER_V1 is defined, determines whether the type
- * satisfies the DynamicBuffer_v1 requirements.
+ * satisfies the DynamicBuffer_v2 requirements.
*/
template <typename T>
struct is_dynamic_buffer
diff --git a/boost/asio/detail/config.hpp b/boost/asio/detail/config.hpp
index 8fef292b00..683a2b1fd6 100644
--- a/boost/asio/detail/config.hpp
+++ b/boost/asio/detail/config.hpp
@@ -341,7 +341,7 @@
// Compliant C++11 compilers put noexcept specifiers on error_category members.
#if !defined(BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT)
-# if (BOOST_VERSION >= 105300)
+# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 105300)
# define BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT BOOST_NOEXCEPT
# elif defined(__clang__)
# if __has_feature(__cxx_noexcept__)
@@ -508,9 +508,9 @@
// Boost support for chrono.
#if !defined(BOOST_ASIO_HAS_BOOST_CHRONO)
# if !defined(BOOST_ASIO_DISABLE_BOOST_CHRONO)
-# if (BOOST_VERSION >= 104700)
+# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 104700)
# define BOOST_ASIO_HAS_BOOST_CHRONO 1
-# endif // (BOOST_VERSION >= 104700)
+# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 104700)
# endif // !defined(BOOST_ASIO_DISABLE_BOOST_CHRONO)
#endif // !defined(BOOST_ASIO_HAS_BOOST_CHRONO)
@@ -1232,6 +1232,8 @@
# define BOOST_ASIO_HAS_THREADS 1
# elif defined(__APPLE__)
# define BOOST_ASIO_HAS_THREADS 1
+# elif defined(__HAIKU__)
+# define BOOST_ASIO_HAS_THREADS 1
# elif defined(_POSIX_THREADS) && (_POSIX_THREADS + 0 >= 0)
# define BOOST_ASIO_HAS_THREADS 1
# elif defined(_PTHREADS)
@@ -1247,6 +1249,8 @@
# define BOOST_ASIO_HAS_PTHREADS 1
# elif defined(_POSIX_THREADS) && (_POSIX_THREADS + 0 >= 0)
# define BOOST_ASIO_HAS_PTHREADS 1
+# elif defined(__HAIKU__)
+# define BOOST_ASIO_HAS_PTHREADS 1
# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS)
# endif // defined(BOOST_ASIO_HAS_THREADS)
#endif // !defined(BOOST_ASIO_HAS_PTHREADS)
@@ -1427,11 +1431,11 @@
# endif // defined(BOOST_ASIO_MSVC)
# endif // !defined(BOOST_ASIO_DISABLE_CO_AWAIT)
# if defined(__clang__)
-# if (__cpp_coroutines >= 201703)
+# if (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)
# if __has_include(<experimental/coroutine>)
# define BOOST_ASIO_HAS_CO_AWAIT 1
# endif // __has_include(<experimental/coroutine>)
-# endif // (__cpp_coroutines >= 201703)
+# endif // (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)
# endif // defined(__clang__)
#endif // !defined(BOOST_ASIO_HAS_CO_AWAIT)
diff --git a/boost/asio/detail/impl/win_iocp_handle_service.ipp b/boost/asio/detail/impl/win_iocp_handle_service.ipp
index 1256c358ac..da33768b2b 100644
--- a/boost/asio/detail/impl/win_iocp_handle_service.ipp
+++ b/boost/asio/detail/impl/win_iocp_handle_service.ipp
@@ -243,7 +243,8 @@ boost::system::error_code win_iocp_handle_service::cancel(
{
// The version of Windows supports cancellation from any thread.
typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
- cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
+ cancel_io_ex_t cancel_io_ex = reinterpret_cast<cancel_io_ex_t>(
+ reinterpret_cast<void*>(cancel_io_ex_ptr));
if (!cancel_io_ex(impl.handle_, 0))
{
DWORD last_error = ::GetLastError();
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 4e30b0f678..a8133fa3fa 100644
--- a/boost/asio/detail/impl/win_iocp_serial_port_service.ipp
+++ b/boost/asio/detail/impl/win_iocp_serial_port_service.ipp
@@ -80,11 +80,22 @@ boost::system::error_code win_iocp_serial_port_service::open(
}
// Set some default serial port parameters. This implementation does not
- // support changing these, so they might as well be in a known state.
+ // support changing all of these, so they might as well be in a known state.
dcb.fBinary = TRUE; // Win32 only supports binary mode.
- dcb.fDsrSensitivity = FALSE;
dcb.fNull = FALSE; // Do not ignore NULL characters.
dcb.fAbortOnError = FALSE; // Ignore serial framing errors.
+ dcb.BaudRate = 0; // 0 baud by default
+ dcb.ByteSize = 8; // 8 bit bytes
+ dcb.fOutxCtsFlow = FALSE; // No flow control
+ dcb.fOutxDsrFlow = FALSE;
+ dcb.fDtrControl = DTR_CONTROL_DISABLE;
+ dcb.fDsrSensitivity = FALSE;
+ dcb.fOutX = FALSE;
+ dcb.fInX = FALSE;
+ dcb.fRtsControl = DTR_CONTROL_DISABLE;
+ dcb.fParity = FALSE; // No parity
+ dcb.Parity = NOPARITY;
+ dcb.StopBits = ONESTOPBIT; // One stop bit
if (!::SetCommState(handle, &dcb))
{
DWORD last_error = ::GetLastError();
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 f95c74ff58..5691cdb9e7 100644
--- a/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
+++ b/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
@@ -250,7 +250,8 @@ boost::system::error_code win_iocp_socket_service_base::cancel(
{
// The version of Windows supports cancellation from any thread.
typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
- cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
+ cancel_io_ex_t cancel_io_ex = reinterpret_cast<cancel_io_ex_t>(
+ reinterpret_cast<void*>(cancel_io_ex_ptr));
socket_type sock = impl.socket_;
HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
if (!cancel_io_ex(sock_as_handle, 0))
diff --git a/boost/asio/detail/io_object_executor.hpp b/boost/asio/detail/io_object_executor.hpp
index 70b026b476..5b5258fcd6 100644
--- a/boost/asio/detail/io_object_executor.hpp
+++ b/boost/asio/detail/io_object_executor.hpp
@@ -113,6 +113,13 @@ public:
// When using a native implementation, I/O completion handlers are
// already dispatched according to the execution context's executor's
// rules. We can call the function directly.
+#if defined(BOOST_ASIO_HAS_MOVE)
+ if (is_same<F, typename decay<F>::type>::value)
+ {
+ boost_asio_handler_invoke_helpers::invoke(f, f);
+ return;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
typename decay<F>::type function(BOOST_ASIO_MOVE_CAST(F)(f));
boost_asio_handler_invoke_helpers::invoke(function, function);
}
diff --git a/boost/asio/detail/is_buffer_sequence.hpp b/boost/asio/detail/is_buffer_sequence.hpp
index 89b8df762d..c52103206c 100644
--- a/boost/asio/detail/is_buffer_sequence.hpp
+++ b/boost/asio/detail/is_buffer_sequence.hpp
@@ -54,19 +54,22 @@ struct buffer_sequence_memfns_check
{
};
-template <typename>
-char (&buffer_sequence_begin_helper(...))[2];
-
#if defined(BOOST_ASIO_HAS_DECLTYPE)
+template <typename>
+char buffer_sequence_begin_helper(...);
+
template <typename T>
-char buffer_sequence_begin_helper(T* t,
+char (&buffer_sequence_begin_helper(T* t,
typename enable_if<!is_same<
decltype(boost::asio::buffer_sequence_begin(*t)),
- void>::value>::type*);
+ void>::value>::type*))[2];
#else // defined(BOOST_ASIO_HAS_DECLTYPE)
+template <typename>
+char (&buffer_sequence_begin_helper(...))[2];
+
template <typename T>
char buffer_sequence_begin_helper(T* t,
buffer_sequence_memfns_check<
@@ -75,19 +78,22 @@ char buffer_sequence_begin_helper(T* t,
#endif // defined(BOOST_ASIO_HAS_DECLTYPE)
-template <typename>
-char (&buffer_sequence_end_helper(...))[2];
-
#if defined(BOOST_ASIO_HAS_DECLTYPE)
+template <typename>
+char buffer_sequence_end_helper(...);
+
template <typename T>
-char buffer_sequence_end_helper(T* t,
+char (&buffer_sequence_end_helper(T* t,
typename enable_if<!is_same<
decltype(boost::asio::buffer_sequence_end(*t)),
- void>::value>::type*);
+ void>::value>::type*))[2];
#else // defined(BOOST_ASIO_HAS_DECLTYPE)
+template <typename>
+char (&buffer_sequence_end_helper(...))[2];
+
template <typename T>
char buffer_sequence_end_helper(T* t,
buffer_sequence_memfns_check<
@@ -215,8 +221,8 @@ char mutable_buffers_type_typedef_helper(
template <typename T, typename Buffer>
struct is_buffer_sequence_class
: integral_constant<bool,
- sizeof(buffer_sequence_begin_helper<T>(0)) != 1 &&
- sizeof(buffer_sequence_end_helper<T>(0)) != 1 &&
+ sizeof(buffer_sequence_begin_helper<T>(0, 0)) != 1 &&
+ sizeof(buffer_sequence_end_helper<T>(0, 0)) != 1 &&
sizeof(buffer_sequence_element_type_helper<T, Buffer>(0, 0)) == 1>
{
};
diff --git a/boost/asio/detail/winrt_ssocket_service.hpp b/boost/asio/detail/winrt_ssocket_service.hpp
index af2c718699..272426939f 100644
--- a/boost/asio/detail/winrt_ssocket_service.hpp
+++ b/boost/asio/detail/winrt_ssocket_service.hpp
@@ -179,6 +179,14 @@ public:
return endpoint;
}
+ // Disable sends or receives on the socket.
+ boost::system::error_code shutdown(implementation_type&,
+ socket_base::shutdown_type, boost::system::error_code& ec)
+ {
+ ec = boost::asio::error::operation_not_supported;
+ return ec;
+ }
+
// Set a socket option.
template <typename Option>
boost::system::error_code set_option(implementation_type& impl,
diff --git a/boost/asio/detail/winrt_ssocket_service_base.hpp b/boost/asio/detail/winrt_ssocket_service_base.hpp
index cb7b6c07f7..9bead3222b 100644
--- a/boost/asio/detail/winrt_ssocket_service_base.hpp
+++ b/boost/asio/detail/winrt_ssocket_service_base.hpp
@@ -169,14 +169,6 @@ public:
return ec;
}
- // Disable sends or receives on the socket.
- boost::system::error_code shutdown(base_implementation_type&,
- socket_base::shutdown_type, boost::system::error_code& ec)
- {
- ec = boost::asio::error::operation_not_supported;
- return ec;
- }
-
// Send the given data to the peer.
template <typename ConstBufferSequence>
std::size_t send(base_implementation_type& impl,
diff --git a/boost/asio/impl/connect.hpp b/boost/asio/impl/connect.hpp
index 51e5e6cb16..7089316e1c 100644
--- a/boost/asio/impl/connect.hpp
+++ b/boost/asio/impl/connect.hpp
@@ -372,7 +372,7 @@ namespace detail
return;
}
- default:
+ /* fall-through */ default:
if (iter == end)
break;
@@ -542,7 +542,7 @@ namespace detail
return;
}
- default:
+ /* fall-through */ default:
if (iter_ == end_)
break;
diff --git a/boost/asio/ssl/detail/impl/openssl_init.ipp b/boost/asio/ssl/detail/impl/openssl_init.ipp
index 5e80dd2556..dd524c3d17 100644
--- a/boost/asio/ssl/detail/impl/openssl_init.ipp
+++ b/boost/asio/ssl/detail/impl/openssl_init.ipp
@@ -86,9 +86,9 @@ public:
#endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)
// && (OPENSSL_VERSION_NUMBER < 0x10100000L)
// && !defined(SSL_OP_NO_COMPRESSION)
-#if !defined(OPENSSL_IS_BORINGSSL)
+#if !defined(OPENSSL_IS_BORINGSSL) && !defined(BOOST_ASIO_USE_WOLFSSL)
::CONF_modules_unload(1);
-#endif // !defined(OPENSSL_IS_BORINGSSL)
+#endif // !defined(OPENSSL_IS_BORINGSSL) && !defined(BOOST_ASIO_USE_WOLFSSL)
#if !defined(OPENSSL_NO_ENGINE) \
&& (OPENSSL_VERSION_NUMBER < 0x10100000L)
::ENGINE_cleanup();
diff --git a/boost/asio/ssl/detail/openssl_types.hpp b/boost/asio/ssl/detail/openssl_types.hpp
index 494287a36e..ae14947298 100644
--- a/boost/asio/ssl/detail/openssl_types.hpp
+++ b/boost/asio/ssl/detail/openssl_types.hpp
@@ -17,6 +17,9 @@
#include <boost/asio/detail/config.hpp>
#include <boost/asio/detail/socket_types.hpp>
+#if defined(BOOST_ASIO_USE_WOLFSSL)
+# include <wolfssl/options.h>
+#endif // defined(BOOST_ASIO_USE_WOLFSSL)
#include <openssl/conf.h>
#include <openssl/ssl.h>
#if !defined(OPENSSL_NO_ENGINE)
diff --git a/boost/asio/ssl/error.hpp b/boost/asio/ssl/error.hpp
index e9ce78718c..d96e906134 100644
--- a/boost/asio/ssl/error.hpp
+++ b/boost/asio/ssl/error.hpp
@@ -55,7 +55,9 @@ enum stream_errors
/// call.
unexpected_result
#else // defined(GENERATING_DOCUMENTATION)
-# if (OPENSSL_VERSION_NUMBER < 0x10100000L) && !defined(OPENSSL_IS_BORINGSSL)
+# if (OPENSSL_VERSION_NUMBER < 0x10100000L) \
+ && !defined(OPENSSL_IS_BORINGSSL) \
+ && !defined(BOOST_ASIO_USE_WOLFSSL)
stream_truncated = ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ),
# else
stream_truncated = 1,
diff --git a/boost/asio/ssl/impl/context.ipp b/boost/asio/ssl/impl/context.ipp
index 0947a87564..1f9376ab5f 100644
--- a/boost/asio/ssl/impl/context.ipp
+++ b/boost/asio/ssl/impl/context.ipp
@@ -387,7 +387,9 @@ context::~context()
{
if (handle_)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
+#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
+ && !defined(LIBRESSL_VERSION_NUMBER)) \
+ || defined(BOOST_ASIO_USE_WOLFSSL)
void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
void* cb_userdata = handle_->default_passwd_callback_userdata;
@@ -398,7 +400,9 @@ context::~context()
static_cast<detail::password_callback_base*>(
cb_userdata);
delete callback;
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
+#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
+ && !defined(LIBRESSL_VERSION_NUMBER)) \
+ || defined(BOOST_ASIO_USE_WOLFSSL)
::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0);
#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
handle_->default_passwd_callback_userdata = 0;
@@ -735,7 +739,9 @@ BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain(
bio_cleanup bio = { make_buffer_bio(chain) };
if (bio.p)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
+#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
+ && !defined(LIBRESSL_VERSION_NUMBER)) \
+ || defined(BOOST_ASIO_USE_WOLFSSL)
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)
@@ -762,7 +768,9 @@ BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain(
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
-#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && !defined(LIBRESSL_VERSION_NUMBER)
+#if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) \
+ && !defined(LIBRESSL_VERSION_NUMBER)) \
+ || defined(BOOST_ASIO_USE_WOLFSSL)
::SSL_CTX_clear_chain_certs(handle_);
#else
if (handle_->extra_certs)
@@ -839,7 +847,9 @@ BOOST_ASIO_SYNC_OP_VOID context::use_private_key(
{
::ERR_clear_error();
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
+#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
+ && !defined(LIBRESSL_VERSION_NUMBER)) \
+ || defined(BOOST_ASIO_USE_WOLFSSL)
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)
@@ -906,7 +916,9 @@ BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key(
{
::ERR_clear_error();
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
+#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
+ && !defined(LIBRESSL_VERSION_NUMBER)) \
+ || defined(BOOST_ASIO_USE_WOLFSSL)
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)
@@ -1145,7 +1157,9 @@ int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
BOOST_ASIO_SYNC_OP_VOID context::do_set_password_callback(
detail::password_callback_base* callback, boost::system::error_code& ec)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
+#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \
+ && !defined(LIBRESSL_VERSION_NUMBER)) \
+ || defined(BOOST_ASIO_USE_WOLFSSL)
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/version.hpp b/boost/asio/version.hpp
index 30d7b2348e..b93824d41c 100644
--- a/boost/asio/version.hpp
+++ b/boost/asio/version.hpp
@@ -18,6 +18,6 @@
// BOOST_ASIO_VERSION % 100 is the sub-minor version
// BOOST_ASIO_VERSION / 100 % 1000 is the minor version
// BOOST_ASIO_VERSION / 100000 is the major version
-#define BOOST_ASIO_VERSION 101400 // 1.14.0
+#define BOOST_ASIO_VERSION 101401 // 1.14.1
#endif // BOOST_ASIO_VERSION_HPP
diff --git a/boost/beast/_experimental/http/impl/icy_stream.hpp b/boost/beast/_experimental/http/impl/icy_stream.hpp
index f7329180ee..9b6e66ab92 100644
--- a/boost/beast/_experimental/http/impl/icy_stream.hpp
+++ b/boost/beast/_experimental/http/impl/icy_stream.hpp
@@ -35,7 +35,7 @@ is_icy(ConstBufferSequence const& buffers)
char buf[3];
auto const n = net::buffer_copy(
net::mutable_buffer(buf, 3),
- buffers);
+ buffers);
if(n >= 1 && buf[0] != 'I')
return false;
if(n >= 2 && buf[1] != 'C')
@@ -57,7 +57,7 @@ template<class Buffers, class Handler>
class read_op
: public beast::async_base<Handler,
beast::executor_type<icy_stream>>
- , public net::coroutine
+ , public asio::coroutine
{
icy_stream& s_;
Buffers b_;
diff --git a/boost/beast/_experimental/test/impl/stream.hpp b/boost/beast/_experimental/test/impl/stream.hpp
index 53bd4db7c8..3925d7421f 100644
--- a/boost/beast/_experimental/test/impl/stream.hpp
+++ b/boost/beast/_experimental/test/impl/stream.hpp
@@ -12,9 +12,8 @@
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/buffer_traits.hpp>
-#include <boost/beast/core/buffers_prefix.hpp>
#include <boost/beast/core/detail/service_base.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
+#include <boost/beast/core/detail/is_invocable.hpp>
#include <mutex>
#include <stdexcept>
#include <vector>
@@ -108,6 +107,7 @@ class stream::read_op : public stream::read_op_base
net::buffer_copy(
b_, sp->b.data(), sp->read_max);
sp->b.consume(bytes_transferred);
+ sp->nread_bytes += bytes_transferred;
}
else if (buffer_bytes(b_) > 0)
{
@@ -232,6 +232,7 @@ struct stream::run_write_op
std::lock_guard<std::mutex> lock(out->m);
n = net::buffer_copy(out->b.prepare(n), buffers);
out->b.commit(n);
+ out->nwrite_bytes += n;
out->notify_read();
}
BOOST_ASSERT(! ec);
@@ -295,6 +296,7 @@ read_some(MutableBufferSequence const& buffers,
auto const n = net::buffer_copy(
buffers, in_->b.data(), in_->read_max);
in_->b.consume(n);
+ in_->nread_bytes += n;
return n;
}
@@ -378,6 +380,7 @@ write_some(
std::lock_guard<std::mutex> lock(out->m);
n = net::buffer_copy(out->b.prepare(n), buffers);
out->b.commit(n);
+ out->nwrite_bytes += n;
out->notify_read();
}
return n;
diff --git a/boost/beast/_experimental/test/impl/stream.ipp b/boost/beast/_experimental/test/impl/stream.ipp
index 38b8a8b2a4..1570ccaac0 100644
--- a/boost/beast/_experimental/test/impl/stream.ipp
+++ b/boost/beast/_experimental/test/impl/stream.ipp
@@ -13,7 +13,6 @@
#include <boost/beast/_experimental/test/stream.hpp>
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/buffer_traits.hpp>
-#include <boost/beast/core/buffers_prefix.hpp>
#include <boost/make_shared.hpp>
#include <stdexcept>
#include <vector>
@@ -262,6 +261,9 @@ connect(stream& remote)
{
BOOST_ASSERT(! out_.lock());
BOOST_ASSERT(! remote.out_.lock());
+ std::lock(in_->m, remote.in_->m);
+ std::lock_guard<std::mutex> guard1{in_->m, std::adopt_lock};
+ std::lock_guard<std::mutex> guard2{remote.in_->m, std::adopt_lock};
out_ = remote.in_;
remote.out_ = in_;
in_->code = status::ok;
@@ -275,7 +277,7 @@ str() const
auto const bs = in_->b.data();
if(buffer_bytes(bs) == 0)
return {};
- auto const b = beast::buffers_front(bs);
+ net::const_buffer const b = *net::buffer_sequence_begin(bs);
return {static_cast<char const*>(b.data()), b.size()};
}
diff --git a/boost/beast/_experimental/test/stream.hpp b/boost/beast/_experimental/test/stream.hpp
index 181acec9aa..eb12e8d840 100644
--- a/boost/beast/_experimental/test/stream.hpp
+++ b/boost/beast/_experimental/test/stream.hpp
@@ -141,7 +141,9 @@ class stream
status code = status::ok;
fail_count* fc = nullptr;
std::size_t nread = 0;
+ std::size_t nread_bytes = 0;
std::size_t nwrite = 0;
+ std::size_t nwrite_bytes = 0;
std::size_t read_max =
(std::numeric_limits<std::size_t>::max)();
std::size_t write_max =
@@ -361,6 +363,13 @@ public:
return in_->nread;
}
+ /// Return the number of bytes read
+ std::size_t
+ nread_bytes() const noexcept
+ {
+ return in_->nread_bytes;
+ }
+
/// Return the number of writes
std::size_t
nwrite() const noexcept
@@ -368,6 +377,13 @@ public:
return in_->nwrite;
}
+ /// Return the number of bytes written
+ std::size_t
+ nwrite_bytes() const noexcept
+ {
+ return in_->nwrite_bytes;
+ }
+
/** Close the stream.
The other end of the connection will see
diff --git a/boost/beast/_experimental/unit_test/thread.hpp b/boost/beast/_experimental/unit_test/thread.hpp
deleted file mode 100644
index ed06cb3731..0000000000
--- a/boost/beast/_experimental/unit_test/thread.hpp
+++ /dev/null
@@ -1,128 +0,0 @@
-//
-// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Official repository: https://github.com/boostorg/beast
-//
-
-#ifndef BOOST_BEAST_UNIT_TEST_THREAD_HPP
-#define BOOST_BEAST_UNIT_TEST_THREAD_HPP
-
-#include <boost/beast/_experimental/unit_test/suite.hpp>
-#include <functional>
-#include <thread>
-#include <utility>
-
-namespace boost {
-namespace beast {
-namespace unit_test {
-
-/** Replacement for std::thread that handles exceptions in unit tests. */
-class thread
-{
-private:
- suite* s_ = nullptr;
- std::thread t_;
-
-public:
- using id = std::thread::id;
- using native_handle_type = std::thread::native_handle_type;
-
- thread() = default;
- thread(thread const&) = delete;
- thread& operator=(thread const&) = delete;
-
- thread(thread&& other)
- : s_(other.s_)
- , t_(std::move(other.t_))
- {
- }
-
- thread& operator=(thread&& other)
- {
- s_ = other.s_;
- t_ = std::move(other.t_);
- return *this;
- }
-
- template<class F, class... Args>
- explicit
- thread(suite& s, F&& f, Args&&... args)
- : s_(&s)
- {
- std::function<void(void)> b =
- std::bind(std::forward<F>(f),
- std::forward<Args>(args)...);
- t_ = std::thread(&thread::run, this,
- std::move(b));
- }
-
- bool
- joinable() const
- {
- return t_.joinable();
- }
-
- std::thread::id
- get_id() const
- {
- return t_.get_id();
- }
-
- static
- unsigned
- hardware_concurrency() noexcept
- {
- return std::thread::hardware_concurrency();
- }
-
- void
- join()
- {
- t_.join();
- s_->propagate_abort();
- }
-
- void
- detach()
- {
- t_.detach();
- }
-
- void
- swap(thread& other)
- {
- std::swap(s_, other.s_);
- std::swap(t_, other.t_);
- }
-
-private:
- void
- run(std::function <void(void)> f)
- {
- try
- {
- f();
- }
- catch(suite::abort_exception const&)
- {
- }
- catch(std::exception const& e)
- {
- s_->fail("unhandled exception: " +
- std::string(e.what()));
- }
- catch(...)
- {
- s_->fail("unhandled exception");
- }
- }
-};
-
-} // unit_test
-} // beast
-} // boost
-
-#endif
diff --git a/boost/beast/core/basic_stream.hpp b/boost/beast/core/basic_stream.hpp
index 057ab07ffd..25076059e2 100644
--- a/boost/beast/core/basic_stream.hpp
+++ b/boost/beast/core/basic_stream.hpp
@@ -73,7 +73,7 @@ namespace beast {
be invoked by the executor associated with the stream upon construction.
The type of executor used with this stream must meet the following
requirements:
-
+
@li Function objects submitted to the executor shall never run
concurrently with each other.
@@ -284,6 +284,7 @@ private:
// but the implementation is still waiting on a timer.
boost::shared_ptr<impl_type> impl_;
+ template<class Executor2>
struct timeout_handler;
struct ops;
@@ -367,7 +368,7 @@ public:
/** Move constructor
- @param other The other object from which the move will occur.
+ @param other The other object from which the move will occur.
@note Following the move, the moved-from object is in the
same state as if newly constructed.
@@ -490,7 +491,7 @@ public:
//--------------------------------------------------------------------------
/** Get the executor associated with the object.
-
+
This function may be used to obtain the executor object that the
stream uses to dispatch completion handlers without an assocaited
executor.
@@ -498,7 +499,7 @@ public:
@return A copy of the executor that stream will use to dispatch handlers.
*/
executor_type
- get_executor() const noexcept
+ get_executor() noexcept
{
return impl_->ex();
}
@@ -525,7 +526,7 @@ public:
}
/** Connect the stream to the specified endpoint.
-
+
This function is used to connect the underlying socket to the
specified remote endpoint. The function call will block until
the connection is successfully made or an error occurs.
@@ -534,7 +535,7 @@ public:
closed state upon failure.
@param ep The remote endpoint to connect to.
-
+
@param ec Set to indicate what error occurred, if any.
@see connect
@@ -546,7 +547,7 @@ public:
}
/** Establishes a connection by trying each endpoint in a sequence.
-
+
This function attempts to connect the stream to one of a sequence of
endpoints by trying each endpoint until a connection is successfully
established.
@@ -556,11 +557,11 @@ public:
The algorithm, known as a <em>composed operation</em>, is implemented
in terms of calls to the underlying socket's `connect` function.
-
+
@param endpoints A sequence of endpoints.
-
+
@returns The successfully connected endpoint.
-
+
@throws system_error Thrown on failure. If the sequence is
empty, the associated error code is `net::error::not_found`.
Otherwise, contains the error from the last connection attempt.
@@ -579,7 +580,7 @@ public:
}
/** Establishes a connection by trying each endpoint in a sequence.
-
+
This function attempts to connect the stream to one of a sequence of
endpoints by trying each endpoint until a connection is successfully
established.
@@ -589,16 +590,16 @@ public:
The algorithm, known as a <em>composed operation</em>, is implemented
in terms of calls to the underlying socket's `connect` function.
-
+
@param endpoints A sequence of endpoints.
-
+
@param ec Set to indicate what error occurred, if any. If the sequence is
empty, set to `net::error::not_found`. Otherwise, contains the error
from the last connection attempt.
-
+
@returns On success, the successfully connected endpoint. Otherwise, a
default-constructed endpoint.
- */
+ */
template<class EndpointSequence
#if ! BOOST_BEAST_DOXYGEN
,class = typename std::enable_if<
@@ -616,27 +617,27 @@ public:
}
/** Establishes a connection by trying each endpoint in a sequence.
-
+
This function attempts to connect the stream to one of a sequence of
endpoints by trying each endpoint until a connection is successfully
established.
The underlying socket is automatically opened if needed.
An automatically opened socket is not returned to the
closed state upon failure.
-
+
The algorithm, known as a <em>composed operation</em>, is implemented
in terms of calls to the underlying socket's `connect` function.
-
+
@param begin An iterator pointing to the start of a sequence of endpoints.
-
+
@param end An iterator pointing to the end of a sequence of endpoints.
-
+
@returns An iterator denoting the successfully connected endpoint.
-
+
@throws system_error Thrown on failure. If the sequence is
empty, the associated error code is `net::error::not_found`.
Otherwise, contains the error from the last connection attempt.
- */
+ */
template<class Iterator>
Iterator
connect(
@@ -646,25 +647,25 @@ public:
}
/** Establishes a connection by trying each endpoint in a sequence.
-
+
This function attempts to connect the stream to one of a sequence of
endpoints by trying each endpoint until a connection is successfully
established.
The underlying socket is automatically opened if needed.
An automatically opened socket is not returned to the
closed state upon failure.
-
+
The algorithm, known as a <em>composed operation</em>, is implemented
in terms of calls to the underlying socket's `connect` function.
-
+
@param begin An iterator pointing to the start of a sequence of endpoints.
-
+
@param end An iterator pointing to the end of a sequence of endpoints.
-
+
@param ec Set to indicate what error occurred, if any. If the sequence is
empty, set to boost::asio::error::not_found. Otherwise, contains the error
from the last connection attempt.
-
+
@returns On success, an iterator denoting the successfully connected
endpoint. Otherwise, the end iterator.
*/
@@ -678,7 +679,7 @@ public:
}
/** Establishes a connection by trying each endpoint in a sequence.
-
+
This function attempts to connect the stream to one of a sequence of
endpoints by trying each endpoint until a connection is successfully
established.
@@ -688,9 +689,9 @@ public:
The algorithm, known as a <em>composed operation</em>, is implemented
in terms of calls to the underlying socket's `connect` function.
-
+
@param endpoints A sequence of endpoints.
-
+
@param connect_condition A function object that is called prior to each
connection attempt. The signature of the function object must be:
@code
@@ -703,9 +704,9 @@ public:
indicate success. The @c next parameter is the next endpoint to be tried.
The function object should return true if the next endpoint should be tried,
and false if it should be skipped.
-
+
@returns The successfully connected endpoint.
-
+
@throws boost::system::system_error Thrown on failure. If the sequence is
empty, the associated error code is `net::error::not_found`.
Otherwise, contains the error from the last connection attempt.
@@ -779,7 +780,7 @@ public:
}
/** Establishes a connection by trying each endpoint in a sequence.
-
+
This function attempts to connect the stream to one of a sequence of
endpoints by trying each endpoint until a connection is successfully
established.
@@ -789,11 +790,11 @@ public:
The algorithm, known as a <em>composed operation</em>, is implemented
in terms of calls to the underlying socket's `connect` function.
-
+
@param begin An iterator pointing to the start of a sequence of endpoints.
-
+
@param end An iterator pointing to the end of a sequence of endpoints.
-
+
@param connect_condition A function object that is called prior to each
connection attempt. The signature of the function object must be:
@code
@@ -806,13 +807,13 @@ public:
indicate success. The @c next parameter is the next endpoint to be tried.
The function object should return true if the next endpoint should be tried,
and false if it should be skipped.
-
+
@returns An iterator denoting the successfully connected endpoint.
-
+
@throws boost::system::system_error Thrown on failure. If the sequence is
empty, the associated @c error_code is `net::error::not_found`.
Otherwise, contains the error from the last connection attempt.
- */
+ */
template<
class Iterator, class ConnectCondition>
Iterator
@@ -824,7 +825,7 @@ public:
}
/** Establishes a connection by trying each endpoint in a sequence.
-
+
This function attempts to connect the stream to one of a sequence of
endpoints by trying each endpoint until a connection is successfully
established.
@@ -834,11 +835,11 @@ public:
The algorithm, known as a <em>composed operation</em>, is implemented
in terms of calls to the underlying socket's `connect` function.
-
+
@param begin An iterator pointing to the start of a sequence of endpoints.
-
+
@param end An iterator pointing to the end of a sequence of endpoints.
-
+
@param connect_condition A function object that is called prior to each
connection attempt. The signature of the function object must be:
@code
@@ -851,11 +852,11 @@ public:
indicate success. The @c next parameter is the next endpoint to be tried.
The function object should return true if the next endpoint should be tried,
and false if it should be skipped.
-
+
@param ec Set to indicate what error occurred, if any. If the sequence is
empty, set to `net::error::not_found`. Otherwise, contains the error
from the last connection attempt.
-
+
@returns On success, an iterator denoting the successfully connected
endpoint. Otherwise, the end iterator.
*/
@@ -885,7 +886,7 @@ public:
@param ep The remote endpoint to which the underlying socket will be
connected. Copies will be made of the endpoint object as required.
-
+
@param handler The completion handler to invoke when the operation
completes. The implementation takes ownership of the handler by
performing a decay-copy. The equivalent function signature of
@@ -909,7 +910,7 @@ public:
ConnectHandler&& handler);
/** Establishes a connection by trying each endpoint in a sequence asynchronously.
-
+
This function attempts to connect the stream to one of a sequence of
endpoints by trying each endpoint until a connection is successfully
established.
@@ -924,10 +925,10 @@ public:
If the timeout timer expires while the operation is outstanding,
the current connection attempt will be canceled and the completion
handler will be invoked with the error @ref error::timeout.
-
+
@param endpoints A sequence of endpoints. This this object must meet
the requirements of <em>EndpointSequence</em>.
-
+
@param handler The completion handler to invoke when the operation
completes. The implementation takes ownership of the handler by
performing a decay-copy. The equivalent function signature of
@@ -938,7 +939,7 @@ public:
// net::error::not_found. Otherwise, contains the
// error from the last connection attempt.
error_code const& error,
-
+
// On success, the successfully connected endpoint.
// Otherwise, a default-constructed endpoint.
typename Protocol::endpoint const& endpoint
@@ -964,7 +965,7 @@ public:
RangeConnectHandler&& handler);
/** Establishes a connection by trying each endpoint in a sequence asynchronously.
-
+
This function attempts to connect the stream to one of a sequence of
endpoints by trying each endpoint until a connection is successfully
established.
@@ -982,7 +983,7 @@ public:
@param endpoints A sequence of endpoints. This this object must meet
the requirements of <em>EndpointSequence</em>.
-
+
@param connect_condition A function object that is called prior to each
connection attempt. The signature of the function object must be:
@code
@@ -1006,7 +1007,7 @@ public:
// net::error::not_found. Otherwise, contains the
// error from the last connection attempt.
error_code const& error,
-
+
// On success, the successfully connected endpoint.
// Otherwise, a default-constructed endpoint.
typename Protocol::endpoint const& endpoint
@@ -1052,7 +1053,7 @@ public:
RangeConnectHandler&& handler);
/** Establishes a connection by trying each endpoint in a sequence asynchronously.
-
+
This function attempts to connect the stream to one of a sequence of
endpoints by trying each endpoint until a connection is successfully
established.
@@ -1067,9 +1068,9 @@ public:
If the timeout timer expires while the operation is outstanding,
the current connection attempt will be canceled and the completion
handler will be invoked with the error @ref error::timeout.
-
+
@param begin An iterator pointing to the start of a sequence of endpoints.
-
+
@param end An iterator pointing to the end of a sequence of endpoints.
@param handler The completion handler to invoke when the operation
@@ -1082,7 +1083,7 @@ public:
// net::error::not_found. Otherwise, contains the
// error from the last connection attempt.
error_code const& error,
-
+
// On success, an iterator denoting the successfully
// connected endpoint. Otherwise, the end iterator.
Iterator iterator
@@ -1102,7 +1103,7 @@ public:
IteratorConnectHandler&& handler);
/** Establishes a connection by trying each endpoint in a sequence asynchronously.
-
+
This function attempts to connect the stream to one of a sequence of
endpoints by trying each endpoint until a connection is successfully
established.
@@ -1113,11 +1114,11 @@ public:
If the timeout timer expires while the operation is outstanding,
the current connection attempt will be canceled and the completion
handler will be invoked with the error @ref error::timeout.
-
+
@param begin An iterator pointing to the start of a sequence of endpoints.
@param end An iterator pointing to the end of a sequence of endpoints.
-
+
@param connect_condition A function object that is called prior to each
connection attempt. The signature of the function object must be:
@code
@@ -1136,7 +1137,7 @@ public:
// net::error::not_found. Otherwise, contains the
// error from the last connection attempt.
error_code const& error,
-
+
// On success, an iterator denoting the successfully
// connected endpoint. Otherwise, the end iterator.
Iterator iterator
@@ -1162,7 +1163,7 @@ public:
/** Read some data.
This function is used to read some data from the stream.
-
+
The call blocks until one of the following is true:
@li One or more bytes are read from the stream.
@@ -1172,11 +1173,11 @@ public:
@param buffers The buffers into which the data will be read. If the
size of the buffers is zero bytes, the call always returns
immediately with no error.
-
+
@returns The number of bytes read.
-
+
@throws system_error Thrown on failure.
-
+
@note The `read_some` operation may not receive all of the requested
number of bytes. Consider using the function `net::read` if you need
to ensure that the requested amount of data is read before the
@@ -1202,11 +1203,11 @@ public:
@param buffers The buffers into which the data will be read. If the
size of the buffers is zero bytes, the call always returns
immediately with no error.
-
+
@param ec Set to indicate what error occurred, if any.
@returns The number of bytes read.
-
+
@note The `read_some` operation may not receive all of the requested
number of bytes. Consider using the function `net::read` if you need
to ensure that the requested amount of data is read before the
@@ -1224,7 +1225,7 @@ public:
/** Read some data asynchronously.
This function is used to asynchronously read data from the stream.
-
+
This call always returns immediately. The asynchronous operation
will continue until one of the following conditions is true:
@@ -1247,7 +1248,7 @@ public:
Although the buffers object may be copied as necessary, ownership of the
underlying memory blocks is retained by the caller, which must guarantee
that they remain valid until the handler is called.
-
+
@param handler The completion handler to invoke when the operation
completes. The implementation takes ownership of the handler by
performing a decay-copy. The equivalent function signature of
@@ -1277,7 +1278,7 @@ public:
/** Write some data.
This function is used to write some data to the stream.
-
+
The call blocks until one of the following is true:
@li One or more bytes are written to the stream.
@@ -1289,9 +1290,9 @@ public:
with no error.
@returns The number of bytes written.
-
+
@throws system_error Thrown on failure.
-
+
@note The `write_some` operation may not transmit all of the requested
number of bytes. Consider using the function `net::write` if you need
to ensure that the requested amount of data is written before the
@@ -1307,7 +1308,7 @@ public:
/** Write some data.
This function is used to write some data to the stream.
-
+
The call blocks until one of the following is true:
@li One or more bytes are written to the stream.
@@ -1321,9 +1322,9 @@ public:
@param ec Set to indicate what error occurred, if any.
@returns The number of bytes written.
-
+
@throws system_error Thrown on failure.
-
+
@note The `write_some` operation may not transmit all of the requested
number of bytes. Consider using the function `net::write` if you need
to ensure that the requested amount of data is written before the
@@ -1341,7 +1342,7 @@ public:
/** Write some data asynchronously.
This function is used to asynchronously write data to the underlying socket.
-
+
This call always returns immediately. The asynchronous operation
will continue until one of the following conditions is true:
@@ -1364,7 +1365,7 @@ public:
Although the buffers object may be copied as necessary, ownership of the
underlying memory blocks is retained by the caller, which must guarantee
that they remain valid until the handler is called.
-
+
@param handler The completion handler to invoke when the operation
completes. The implementation takes ownership of the handler by
performing a decay-copy. The equivalent function signature of
diff --git a/boost/beast/core/buffers_cat.hpp b/boost/beast/core/buffers_cat.hpp
index 532ea32eef..f13732916b 100644
--- a/boost/beast/core/buffers_cat.hpp
+++ b/boost/beast/core/buffers_cat.hpp
@@ -19,7 +19,6 @@ namespace boost {
namespace beast {
/** A buffer sequence representing a concatenation of buffer sequences.
-
@see buffers_cat
*/
template<class... Buffers>
@@ -29,7 +28,6 @@ class buffers_cat_view
public:
/** The type of buffer returned when dereferencing an iterator.
-
If every buffer sequence in the view is a <em>MutableBufferSequence</em>,
then `value_type` will be `net::mutable_buffer`.
Otherwise, `value_type` will be `net::const_buffer`.
@@ -50,7 +48,6 @@ public:
buffers_cat_view& operator=(buffers_cat_view const&) = default;
/** Constructor
-
@param buffers The list of buffer sequences to concatenate.
Copies of the arguments will be maintained for the lifetime
of the concatenated sequence; however, the ownership of the
@@ -63,12 +60,12 @@ public:
const_iterator
begin() const;
- /// Returns an iterator to one past the last buffer in the sequence
+ /// Returns an iterator to one past the last buffer in the sequence
const_iterator
end() const;
};
-/** Concatenate 2 or more buffer sequences.
+/** Concatenate 1 or more buffer sequences.
This function returns a constant or mutable buffer sequence which,
when iterated, efficiently concatenates the input buffer sequences.
@@ -76,15 +73,12 @@ public:
object does not take ownership of the underlying memory. The
application is still responsible for managing the lifetime of the
referenced memory.
-
@param buffers The list of buffer sequences to concatenate.
-
@return A new buffer sequence that represents the concatenation of
the input buffer sequences. This buffer sequence will be a
<em>MutableBufferSequence</em> if each of the passed buffer sequences is
also a <em>MutableBufferSequence</em>; otherwise the returned buffer
sequence will be a <em>ConstBufferSequence</em>.
-
@see buffers_cat_view
*/
#if BOOST_BEAST_DOXYGEN
@@ -92,15 +86,15 @@ template<class... BufferSequence>
buffers_cat_view<BufferSequence...>
buffers_cat(BufferSequence const&... buffers)
#else
-template<class B1, class B2, class... Bn>
-buffers_cat_view<B1, B2, Bn...>
-buffers_cat(B1 const& b1, B2 const& b2, Bn const&... bn)
+template<class B1, class... Bn>
+buffers_cat_view<B1, Bn...>
+buffers_cat(B1 const& b1, Bn const&... bn)
#endif
{
static_assert(
- is_const_buffer_sequence<B1, B2, Bn...>::value,
+ is_const_buffer_sequence<B1, Bn...>::value,
"BufferSequence type requirements not met");
- return buffers_cat_view<B1, B2, Bn...>{b1, b2, bn...};
+ return buffers_cat_view<B1, Bn...>{b1, bn...};
}
} // beast
diff --git a/boost/beast/core/detail/base64.hpp b/boost/beast/core/detail/base64.hpp
index 7f91c04777..477fecf2a6 100644
--- a/boost/beast/core/detail/base64.hpp
+++ b/boost/beast/core/detail/base64.hpp
@@ -12,7 +12,6 @@
#include <boost/beast/core/string.hpp>
#include <cctype>
-#include <string>
#include <utility>
namespace boost {
@@ -78,26 +77,6 @@ decode(void* dest, char const* src, std::size_t len);
} // base64
-BOOST_BEAST_DECL
-std::string
-base64_encode(std::uint8_t const* data, std::size_t len);
-
-BOOST_BEAST_DECL
-std::string
-base64_encode(string_view s);
-
-template<class = void>
-std::string
-base64_decode(string_view data)
-{
- std::string dest;
- dest.resize(base64::decoded_size(data.size()));
- auto const result = base64::decode(
- &dest[0], data.data(), data.size());
- dest.resize(result.first);
- return dest;
-}
-
} // detail
} // beast
} // boost
diff --git a/boost/beast/core/detail/base64.ipp b/boost/beast/core/detail/base64.ipp
index 7e11d188b6..4fc3c6771f 100644
--- a/boost/beast/core/detail/base64.ipp
+++ b/boost/beast/core/detail/base64.ipp
@@ -195,24 +195,6 @@ decode(void* dest, char const* src, std::size_t len)
} // base64
-std::string
-base64_encode(
- std::uint8_t const* data,
- std::size_t len)
-{
- std::string dest;
- dest.resize(base64::encoded_size(len));
- dest.resize(base64::encode(&dest[0], data, len));
- return dest;
-}
-
-std::string
-base64_encode(string_view s)
-{
- return base64_encode (reinterpret_cast <
- std::uint8_t const*> (s.data()), s.size());
-}
-
} // detail
} // beast
} // boost
diff --git a/boost/beast/core/detail/buffers_range_adaptor.hpp b/boost/beast/core/detail/buffers_range_adaptor.hpp
index 2e04d14f6d..e8e5147433 100644
--- a/boost/beast/core/detail/buffers_range_adaptor.hpp
+++ b/boost/beast/core/detail/buffers_range_adaptor.hpp
@@ -38,13 +38,9 @@ public:
buffers_iterator_type<BufferSequence>;
iter_type it_{};
- buffers_range_adaptor const* b_ = nullptr;
- const_iterator(
- buffers_range_adaptor const& b,
- iter_type const& it)
+ const_iterator(iter_type const& it)
: it_(it)
- , b_(&b)
{
}
@@ -62,7 +58,7 @@ public:
bool
operator==(const_iterator const& other) const
{
- return b_ == other.b_ && it_ == other.it_;
+ return it_ == other.it_;
}
bool
@@ -111,11 +107,6 @@ public:
}
};
- buffers_range_adaptor(
- buffers_range_adaptor const&) = default;
- buffers_range_adaptor& operator=(
- buffers_range_adaptor const&) = default;
-
explicit
buffers_range_adaptor(BufferSequence const& b)
: b_(b)
@@ -125,13 +116,13 @@ public:
const_iterator
begin() const noexcept
{
- return {*this, net::buffer_sequence_begin(b_)};
+ return {net::buffer_sequence_begin(b_)};
}
const_iterator
end() const noexcept
{
- return {*this, net::buffer_sequence_end(b_)};
+ return {net::buffer_sequence_end(b_)};
}
};
diff --git a/boost/beast/core/detail/char_buffer.hpp b/boost/beast/core/detail/char_buffer.hpp
new file mode 100644
index 0000000000..b1970ebc0a
--- /dev/null
+++ b/boost/beast/core/detail/char_buffer.hpp
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 2019 Damian Jarek(damian.jarek93@gmail.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_CORE_DETAIL_CHAR_BUFFER_HPP
+#define BOOST_BEAST_CORE_DETAIL_CHAR_BUFFER_HPP
+
+#include <boost/config.hpp>
+#include <cstddef>
+#include <cstring>
+#include <cstdint>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+template <std::size_t N>
+class char_buffer
+{
+public:
+ bool try_push_back(char c)
+ {
+ if (size_ == N)
+ return false;
+ buf_[size_++] = c;
+ return true;
+ }
+
+ bool try_append(char const* first, char const* last)
+ {
+ std::size_t const n = last - first;
+ if (n > N - size_)
+ return false;
+ std::memmove(&buf_[size_], first, n);
+ size_ += n;
+ return true;
+ }
+
+ void clear() noexcept
+ {
+ size_ = 0;
+ }
+
+ char* data() noexcept
+ {
+ return buf_;
+ }
+
+ char const* data() const noexcept
+ {
+ return buf_;
+ }
+
+ std::size_t size() const noexcept
+ {
+ return size_;
+ }
+
+ bool empty() const noexcept
+ {
+ return size_ == 0;
+ }
+
+private:
+ std::size_t size_= 0;
+ char buf_[N];
+};
+
+} // detail
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/core/detail/impl/read.hpp b/boost/beast/core/detail/impl/read.hpp
index 137384aa40..3724979272 100644
--- a/boost/beast/core/detail/impl/read.hpp
+++ b/boost/beast/core/detail/impl/read.hpp
@@ -13,6 +13,7 @@
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/async_base.hpp>
#include <boost/beast/core/flat_static_buffer.hpp>
+#include <boost/beast/core/read_size.hpp>
#include <boost/asio/basic_stream_socket.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/throw_exception.hpp>
@@ -37,7 +38,7 @@ template<
class Condition,
class Handler>
class read_op
- : public net::coroutine
+ : public asio::coroutine
, public async_base<
Handler, beast::executor_type<Stream>>
{
@@ -73,18 +74,12 @@ public:
std::size_t bytes_transferred,
bool cont = true)
{
- std::size_t max_size;
std::size_t max_prepare;
BOOST_ASIO_CORO_REENTER(*this)
{
for(;;)
{
- max_size = cond_(ec, total_, b_);
- max_prepare = std::min<std::size_t>(
- std::max<std::size_t>(
- 512, b_.capacity() - b_.size()),
- std::min<std::size_t>(
- max_size, b_.max_size() - b_.size()));
+ max_prepare = beast::read_size(b_, cond_(ec, total_, b_));
if(max_prepare == 0)
break;
BOOST_ASIO_CORO_YIELD
@@ -201,16 +196,10 @@ read(
"CompletionCondition type requirements not met");
ec = {};
std::size_t total = 0;
- std::size_t max_size;
std::size_t max_prepare;
for(;;)
{
- max_size = cond(ec, total, buffer);
- max_prepare = std::min<std::size_t>(
- std::max<std::size_t>(
- 512, buffer.capacity() - buffer.size()),
- std::min<std::size_t>(
- max_size, buffer.max_size() - buffer.size()));
+ max_prepare = beast::read_size(buffer, cond(ec, total, buffer));
if(max_prepare == 0)
break;
std::size_t const bytes_transferred =
diff --git a/boost/beast/core/detail/impl/temporary_buffer.ipp b/boost/beast/core/detail/impl/temporary_buffer.ipp
new file mode 100644
index 0000000000..932e847371
--- /dev/null
+++ b/boost/beast/core/detail/impl/temporary_buffer.ipp
@@ -0,0 +1,69 @@
+//
+// Copyright (c) 2019 Damian Jarek(damian.jarek93@gmail.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_DETAIL_IMPL_TEMPORARY_BUFFER_IPP
+#define BOOST_BEAST_DETAIL_IMPL_TEMPORARY_BUFFER_IPP
+
+#include <boost/beast/core/detail/temporary_buffer.hpp>
+#include <boost/beast/core/detail/clamp.hpp>
+#include <boost/core/exchange.hpp>
+#include <boost/assert.hpp>
+#include <memory>
+#include <cstring>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+void
+temporary_buffer::
+append(string_view s)
+{
+ grow(s.size());
+ unchecked_append(s);
+}
+
+void
+temporary_buffer::
+append(string_view s1, string_view s2)
+{
+ grow(s1.size() + s2.size());
+ unchecked_append(s1);
+ unchecked_append(s2);
+}
+
+void
+temporary_buffer::
+unchecked_append(string_view s)
+{
+ auto n = s.size();
+ std::memcpy(&data_[size_], s.data(), n);
+ size_ += n;
+}
+
+void
+temporary_buffer::
+grow(std::size_t n)
+{
+ if (capacity_ - size_ >= n)
+ return;
+
+ auto const capacity = (n + size_) * 2u;
+ BOOST_ASSERT(! detail::sum_exceeds(
+ n, size_, capacity));
+ char* const p = new char[capacity];
+ std::memcpy(p, data_, size_);
+ deallocate(boost::exchange(data_, p));
+ capacity_ = capacity;
+}
+} // detail
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/core/detail/ostream.hpp b/boost/beast/core/detail/ostream.hpp
index 65da560179..8785c2e6d8 100644
--- a/boost/beast/core/detail/ostream.hpp
+++ b/boost/beast/core/detail/ostream.hpp
@@ -12,7 +12,6 @@
#include <boost/beast/core/buffers_prefix.hpp>
#include <boost/beast/core/buffers_range.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/throw_exception.hpp>
#include <boost/asio/buffer.hpp>
#include <memory>
diff --git a/boost/beast/core/detail/remap_post_to_defer.hpp b/boost/beast/core/detail/remap_post_to_defer.hpp
index 77f7d8ab20..850a833b52 100644
--- a/boost/beast/core/detail/remap_post_to_defer.hpp
+++ b/boost/beast/core/detail/remap_post_to_defer.hpp
@@ -10,7 +10,6 @@
#ifndef BOOST_BEAST_DETAIL_REMAP_POST_TO_DEFER_HPP
#define BOOST_BEAST_DETAIL_REMAP_POST_TO_DEFER_HPP
-#include <boost/asio/bind_executor.hpp>
#include <boost/asio/is_executor.hpp>
#include <boost/core/empty_value.hpp>
#include <type_traits>
diff --git a/boost/beast/core/detail/service_base.hpp b/boost/beast/core/detail/service_base.hpp
index adec09bbf1..1efe121516 100644
--- a/boost/beast/core/detail/service_base.hpp
+++ b/boost/beast/core/detail/service_base.hpp
@@ -17,14 +17,9 @@ namespace beast {
namespace detail {
template<class T>
-struct service_id : net::execution_context::id
-{
-};
-
-template<class T>
struct service_base : net::execution_context::service
{
- static service_id<T> id;
+ static net::execution_context::id const id;
explicit
service_base(net::execution_context& ctx)
@@ -34,7 +29,7 @@ struct service_base : net::execution_context::service
};
template<class T>
-service_id<T> service_base<T>::id;
+net::execution_context::id const service_base<T>::id;
} // detail
} // beast
diff --git a/boost/beast/core/detail/sha1.hpp b/boost/beast/core/detail/sha1.hpp
index abcc307407..c4c8d5e3fd 100644
--- a/boost/beast/core/detail/sha1.hpp
+++ b/boost/beast/core/detail/sha1.hpp
@@ -11,10 +11,7 @@
#define BOOST_BEAST_DETAIL_SHA1_HPP
#include <boost/beast/core/detail/config.hpp>
-
-#include <algorithm>
#include <cstdint>
-#include <cstring>
// Based on https://github.com/vog/sha1
/*
diff --git a/boost/beast/core/detail/string.hpp b/boost/beast/core/detail/string.hpp
new file mode 100644
index 0000000000..b553c60439
--- /dev/null
+++ b/boost/beast/core/detail/string.hpp
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_DETAIL_STRING_HPP
+#define BOOST_BEAST_DETAIL_STRING_HPP
+
+#include <boost/beast/core/string_type.hpp>
+
+namespace boost {
+namespace beast {
+
+namespace detail {
+
+// Pulling in the UDL directly breaks in some places on MSVC,
+// so introduce a namespace for this purprose.
+namespace string_literals {
+
+inline
+string_view
+operator"" _sv(char const* p, std::size_t n)
+{
+ return string_view{p, n};
+}
+
+} // string_literals
+
+inline
+char
+ascii_tolower(char c)
+{
+ return ((static_cast<unsigned>(c) - 65U) < 26) ?
+ c + 'a' - 'A' : c;
+}
+} // detail
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/core/detail/temporary_buffer.hpp b/boost/beast/core/detail/temporary_buffer.hpp
new file mode 100644
index 0000000000..8285b8f7eb
--- /dev/null
+++ b/boost/beast/core/detail/temporary_buffer.hpp
@@ -0,0 +1,83 @@
+//
+// Copyright (c) 2019 Damian Jarek(damian.jarek93@gmail.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_DETAIL_TEMPORARY_BUFFER_HPP
+#define BOOST_BEAST_DETAIL_TEMPORARY_BUFFER_HPP
+
+#include <boost/beast/core/detail/config.hpp>
+#include <boost/beast/core/string.hpp>
+
+#include <memory>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+struct temporary_buffer
+{
+ temporary_buffer() = default;
+ temporary_buffer(temporary_buffer const&) = delete;
+ temporary_buffer& operator=(temporary_buffer const&) = delete;
+
+ ~temporary_buffer() noexcept
+ {
+ deallocate(data_);
+ }
+
+ BOOST_BEAST_DECL
+ void
+ append(string_view s);
+
+ BOOST_BEAST_DECL
+ void
+ append(string_view s1, string_view s2);
+
+ string_view
+ view() const noexcept
+ {
+ return {data_, size_};
+ }
+
+ bool
+ empty() const noexcept
+ {
+ return size_ == 0;
+ }
+
+private:
+ BOOST_BEAST_DECL
+ void
+ unchecked_append(string_view s);
+
+ BOOST_BEAST_DECL
+ void
+ grow(std::size_t n);
+
+ void
+ deallocate(char* data) noexcept
+ {
+ if (data != buffer_)
+ delete[] data;
+ }
+
+ char buffer_[4096];
+ char* data_ = buffer_;
+ std::size_t capacity_ = sizeof(buffer_);
+ std::size_t size_ = 0;
+};
+
+} // detail
+} // beast
+} // boost
+
+#ifdef BOOST_BEAST_HEADER_ONLY
+#include <boost/beast/core/detail/impl/temporary_buffer.ipp>
+#endif
+
+#endif
diff --git a/boost/beast/core/detail/type_traits.hpp b/boost/beast/core/detail/type_traits.hpp
index 3d895403b3..e94abbb179 100644
--- a/boost/beast/core/detail/type_traits.hpp
+++ b/boost/beast/core/detail/type_traits.hpp
@@ -10,36 +10,14 @@
#ifndef BOOST_BEAST_DETAIL_TYPE_TRAITS_HPP
#define BOOST_BEAST_DETAIL_TYPE_TRAITS_HPP
-#include <boost/beast/core/error.hpp>
-#include <boost/beast/core/detail/is_invocable.hpp>
-#include <boost/asio/buffer.hpp>
-#include <boost/mp11/function.hpp>
#include <boost/type_traits/make_void.hpp>
-#include <iterator>
-#include <tuple>
#include <type_traits>
-#include <string>
-#include <utility>
+#include <new>
namespace boost {
namespace beast {
namespace detail {
-// variadic min
-template<class T>
-T constexpr min(T t)
-{
- return t;
-}
-
-template<class T, class...Tn>
-T constexpr min(T t0, T t1, Tn... tn)
-{
- return (t0 < t1) ?
- (detail::min)(t0, tn...) :
- (detail::min)(t1, tn...);
-}
-
template<class U>
std::size_t constexpr
max_sizeof()
@@ -97,12 +75,6 @@ using aligned_union_t =
//------------------------------------------------------------------------------
-template<class T>
-void
-accept_rv(T){}
-
-//------------------------------------------------------------------------------
-
// for span
template<class T, class E, class = void>
struct is_contiguous_container: std::false_type {};
@@ -124,6 +96,18 @@ struct is_contiguous_container<T, E, void_t<
>::type>>: std::true_type
{};
+template <class T, class U>
+T launder_cast(U* u)
+{
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+ return std::launder(reinterpret_cast<T>(u));
+#elif defined(BOOST_GCC) && BOOST_GCC_VERSION > 80000
+ return __builtin_launder(reinterpret_cast<T>(u));
+#else
+ return reinterpret_cast<T>(u);
+#endif
+}
+
} // detail
} // beast
} // boost
diff --git a/boost/beast/core/detail/variant.hpp b/boost/beast/core/detail/variant.hpp
index 94bd4c040c..f6f5b3c60b 100644
--- a/boost/beast/core/detail/variant.hpp
+++ b/boost/beast/core/detail/variant.hpp
@@ -45,7 +45,7 @@ class variant
{
using T =
mp11::mp_at_c<variant, I::value - 1>;
- reinterpret_cast<T&>(self.buf_).~T();
+ detail::launder_cast<T*>(&self.buf_)->~T();
}
};
@@ -64,7 +64,7 @@ class variant
using T =
mp11::mp_at_c<variant, I::value - 1>;
::new(&self.buf_) T(
- reinterpret_cast<T const&>(other.buf_));
+ *detail::launder_cast<T const*>(&other.buf_));
self.i_ = I::value;
}
};
@@ -83,9 +83,9 @@ class variant
{
using T =
mp11::mp_at_c<variant, I::value - 1>;
- ::new(&self.buf_) T(
- reinterpret_cast<T&&>(other.buf_));
- reinterpret_cast<T&>(other.buf_).~T();
+ ::new(&self.buf_) T(std::move(
+ *detail::launder_cast<T*>(&other.buf_)));
+ detail::launder_cast<T*>(&other.buf_)->~T();
self.i_ = I::value;
}
};
@@ -106,8 +106,8 @@ class variant
using T =
mp11::mp_at_c<variant, I::value - 1>;
return
- reinterpret_cast<T const&>(self.buf_) ==
- reinterpret_cast<T const&>(other.buf_);
+ *detail::launder_cast<T const*>(&self.buf_) ==
+ *detail::launder_cast<T const*>(&other.buf_);
}
};
@@ -181,7 +181,7 @@ public:
}
return *this;
}
-
+
variant& operator=(variant const& other)
{
if(this != &other)
@@ -208,7 +208,7 @@ public:
get()
{
BOOST_ASSERT(i_ == I);
- return *reinterpret_cast<
+ return *detail::launder_cast<
mp11::mp_at_c<variant, I - 1>*>(&buf_);
}
@@ -217,7 +217,7 @@ public:
get() const
{
BOOST_ASSERT(i_ == I);
- return *reinterpret_cast<
+ return *detail::launder_cast<
mp11::mp_at_c<variant, I - 1> const*>(&buf_);
}
diff --git a/boost/beast/core/detect_ssl.hpp b/boost/beast/core/detect_ssl.hpp
index b7b0550175..9281156819 100644
--- a/boost/beast/core/detect_ssl.hpp
+++ b/boost/beast/core/detect_ssl.hpp
@@ -430,7 +430,6 @@ async_detect_ssl(
// Non-const references need to be passed as pointers,
// since we don't want a decay-copy.
-
return net::async_initiate<
CompletionToken,
void(error_code, bool)>(
@@ -505,7 +504,7 @@ public:
AsyncReadStream& stream,
DynamicBuffer& buffer)
: beast::async_base<
- DetectHandler_,
+ DetectHandler,
beast::executor_type<AsyncReadStream>>(
std::forward<DetectHandler_>(handler),
stream.get_executor())
diff --git a/boost/beast/core/impl/async_base.hpp b/boost/beast/core/impl/async_base.hpp
index ec17b1cc1e..8dc8cb29a9 100644
--- a/boost/beast/core/impl/async_base.hpp
+++ b/boost/beast/core/impl/async_base.hpp
@@ -42,8 +42,9 @@ struct allocate_stable_state final
allocate_stable_state>;
A a(this->get());
- detail::allocator_traits<A>::destroy(a, this);
- detail::allocator_traits<A>::deallocate(a, this, 1);
+ auto* p = this;
+ p->~allocate_stable_state();
+ a.deallocate(p, 1);
}
};
@@ -118,33 +119,30 @@ allocate_stable(
{
using allocator_type = typename stable_async_base<
Handler, Executor1, Allocator>::allocator_type;
-
+ using state = detail::allocate_stable_state<
+ State, allocator_type>;
using A = typename detail::allocator_traits<
- allocator_type>::template rebind_alloc<
- detail::allocate_stable_state<
- State, allocator_type>>;
+ allocator_type>::template rebind_alloc<state>;
struct deleter
{
allocator_type alloc;
- detail::allocate_stable_state<
- State, allocator_type>* ptr;
+ state* ptr;
~deleter()
{
if(ptr)
{
A a(alloc);
- detail::allocator_traits<A>::deallocate(a, ptr, 1);
+ a.deallocate(ptr, 1);
}
}
};
A a(base.get_allocator());
- deleter d{base.get_allocator(), nullptr};
- d.ptr = detail::allocator_traits<A>::allocate(a, 1);
- detail::allocator_traits<A>::construct(a, d.ptr,
- d.alloc, std::forward<Args>(args)...);
+ deleter d{base.get_allocator(), a.allocate(1)};
+ ::new(static_cast<void*>(d.ptr))
+ state(d.alloc, std::forward<Args>(args)...);
d.ptr->next_ = base.list_;
base.list_ = d.ptr;
return boost::exchange(d.ptr, nullptr)->value;
diff --git a/boost/beast/core/impl/basic_stream.hpp b/boost/beast/core/impl/basic_stream.hpp
index c871944552..336c09f227 100644
--- a/boost/beast/core/impl/basic_stream.hpp
+++ b/boost/beast/core/impl/basic_stream.hpp
@@ -13,9 +13,7 @@
#include <boost/beast/core/async_base.hpp>
#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/core/buffers_prefix.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/beast/websocket/teardown.hpp>
-#include <boost/asio/bind_executor.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/assert.hpp>
#include <boost/make_shared.hpp>
@@ -161,12 +159,21 @@ close()
//------------------------------------------------------------------------------
template<class Protocol, class Executor, class RatePolicy>
+template<class Executor2>
struct basic_stream<Protocol, Executor, RatePolicy>::
timeout_handler
{
+ using executor_type = Executor2;
+
op_state& state;
boost::weak_ptr<impl_type> wp;
tick_type tick;
+ executor_type ex;
+
+ executor_type get_executor() const noexcept
+ {
+ return ex;
+ }
void
operator()(error_code ec)
@@ -212,62 +219,34 @@ class transfer_op
using is_read = std::integral_constant<bool, isRead>;
op_state&
- state(std::true_type)
- {
- return impl_->read;
- }
-
- op_state&
- state(std::false_type)
- {
- return impl_->write;
- }
-
- op_state&
state()
{
- return state(
- std::integral_constant<bool, isRead>{});
- }
-
- std::size_t
- available_bytes(std::true_type)
- {
- return rate_policy_access::
- available_read_bytes(impl_->policy());
- }
-
- std::size_t
- available_bytes(std::false_type)
- {
- return rate_policy_access::
- available_write_bytes(impl_->policy());
+ if (isRead)
+ return impl_->read;
+ else
+ return impl_->write;
}
std::size_t
available_bytes()
{
- return available_bytes(is_read{});
- }
-
- void
- transfer_bytes(std::size_t n, std::true_type)
- {
- rate_policy_access::
- transfer_read_bytes(impl_->policy(), n);
- }
-
- void
- transfer_bytes(std::size_t n, std::false_type)
- {
- rate_policy_access::
- transfer_write_bytes(impl_->policy(), n);
+ if (isRead)
+ return rate_policy_access::
+ available_read_bytes(impl_->policy());
+ else
+ return rate_policy_access::
+ available_write_bytes(impl_->policy());
}
void
transfer_bytes(std::size_t n)
{
- transfer_bytes(n, is_read{});
+ if (isRead)
+ rate_policy_access::
+ transfer_read_bytes(impl_->policy(), n);
+ else
+ rate_policy_access::
+ transfer_write_bytes(impl_->policy(), n);
}
void
@@ -329,13 +308,11 @@ public:
// if a timeout is active, wait on the timer
if(state().timer.expiry() != never())
state().timer.async_wait(
- net::bind_executor(
- this->get_executor(),
- timeout_handler{
- state(),
- impl_,
- state().tick
- }));
+ timeout_handler<decltype(this->get_executor())>{
+ state(),
+ impl_,
+ state().tick,
+ this->get_executor()});
// check rate limit, maybe wait
std::size_t amount;
@@ -430,12 +407,11 @@ public:
{
if(state().timer.expiry() != stream_base::never())
impl_->write.timer.async_wait(
- net::bind_executor(
- this->get_executor(),
- timeout_handler{
- state(),
- impl_,
- state().tick}));
+ timeout_handler<decltype(this->get_executor())>{
+ state(),
+ impl_,
+ state().tick,
+ this->get_executor()});
impl_->socket.async_connect(
ep, std::move(*this));
@@ -458,12 +434,11 @@ public:
{
if(state().timer.expiry() != stream_base::never())
impl_->write.timer.async_wait(
- net::bind_executor(
- this->get_executor(),
- timeout_handler{
- state(),
- impl_,
- state().tick}));
+ timeout_handler<decltype(this->get_executor())>{
+ state(),
+ impl_,
+ state().tick,
+ this->get_executor()});
net::async_connect(impl_->socket,
eps, cond, std::move(*this));
@@ -486,12 +461,11 @@ public:
{
if(state().timer.expiry() != stream_base::never())
impl_->write.timer.async_wait(
- net::bind_executor(
- this->get_executor(),
- timeout_handler{
- state(),
- impl_,
- state().tick}));
+ timeout_handler<decltype(this->get_executor())>{
+ state(),
+ impl_,
+ state().tick,
+ this->get_executor()});
net::async_connect(impl_->socket,
begin, end, cond, std::move(*this));
diff --git a/boost/beast/core/impl/buffered_read_stream.hpp b/boost/beast/core/impl/buffered_read_stream.hpp
index 184881164f..cea0dcb9fa 100644
--- a/boost/beast/core/impl/buffered_read_stream.hpp
+++ b/boost/beast/core/impl/buffered_read_stream.hpp
@@ -15,7 +15,7 @@
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/read_size.hpp>
#include <boost/beast/core/stream_traits.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
+#include <boost/beast/core/detail/is_invocable.hpp>
#include <boost/asio/post.hpp>
#include <boost/throw_exception.hpp>
diff --git a/boost/beast/core/impl/buffers_adaptor.hpp b/boost/beast/core/impl/buffers_adaptor.hpp
index 91caad5463..3eac32f6e0 100644
--- a/boost/beast/core/impl/buffers_adaptor.hpp
+++ b/boost/beast/core/impl/buffers_adaptor.hpp
@@ -11,7 +11,6 @@
#define BOOST_BEAST_IMPL_BUFFERS_ADAPTOR_HPP
#include <boost/beast/core/buffer_traits.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/config/workaround.hpp>
#include <boost/throw_exception.hpp>
diff --git a/boost/beast/core/impl/buffers_cat.hpp b/boost/beast/core/impl/buffers_cat.hpp
index 255153f2bd..a0506a0b35 100644
--- a/boost/beast/core/impl/buffers_cat.hpp
+++ b/boost/beast/core/impl/buffers_cat.hpp
@@ -11,7 +11,6 @@
#define BOOST_BEAST_IMPL_BUFFERS_CAT_HPP
#include <boost/beast/core/detail/tuple.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/beast/core/detail/variant.hpp>
#include <boost/asio/buffer.hpp>
#include <cstdint>
@@ -23,6 +22,34 @@
namespace boost {
namespace beast {
+template<class Buffer>
+class buffers_cat_view<Buffer>
+{
+ Buffer buffer_;
+public:
+ using value_type = buffers_type<Buffer>;
+
+ using const_iterator = buffers_iterator_type<Buffer>;
+
+ explicit
+ buffers_cat_view(Buffer const& buffer)
+ : buffer_(buffer)
+ {
+ }
+
+ const_iterator
+ begin() const
+ {
+ return net::buffer_sequence_begin(buffer_);
+ }
+
+ const_iterator
+ end() const
+ {
+ return net::buffer_sequence_end(buffer_);
+ }
+};
+
#if defined(_MSC_VER) && ! defined(__clang__)
# define BOOST_BEAST_UNREACHABLE() __assume(false)
# define BOOST_BEAST_UNREACHABLE_RETURN(v) __assume(false)
diff --git a/boost/beast/core/impl/flat_buffer.hpp b/boost/beast/core/impl/flat_buffer.hpp
index f7fd51673d..83d3b4e74b 100644
--- a/boost/beast/core/impl/flat_buffer.hpp
+++ b/boost/beast/core/impl/flat_buffer.hpp
@@ -403,7 +403,7 @@ copy_from(
if(begin_)
{
BOOST_ASSERT(other.begin_);
- std::memcpy(begin_, other.begin_, n);
+ std::memcpy(begin_, other.in_, n);
}
}
diff --git a/boost/beast/core/impl/flat_stream.hpp b/boost/beast/core/impl/flat_stream.hpp
index 2972131198..f99ec02678 100644
--- a/boost/beast/core/impl/flat_stream.hpp
+++ b/boost/beast/core/impl/flat_stream.hpp
@@ -16,7 +16,6 @@
#include <boost/beast/core/stream_traits.hpp>
#include <boost/beast/websocket/teardown.hpp>
#include <boost/asio/buffer.hpp>
-#include <boost/asio/coroutine.hpp>
#include <memory>
namespace boost {
@@ -30,7 +29,6 @@ template<class Handler>
class write_op
: public async_base<Handler,
beast::executor_type<flat_stream>>
- , public net::coroutine
{
public:
template<
diff --git a/boost/beast/core/impl/multi_buffer.hpp b/boost/beast/core/impl/multi_buffer.hpp
index 643f60ce2b..29a10fa17b 100644
--- a/boost/beast/core/impl/multi_buffer.hpp
+++ b/boost/beast/core/impl/multi_buffer.hpp
@@ -11,7 +11,6 @@
#define BOOST_BEAST_IMPL_MULTI_BUFFER_HPP
#include <boost/beast/core/buffer_traits.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/config/workaround.hpp>
#include <boost/core/exchange.hpp>
#include <boost/assert.hpp>
@@ -88,41 +87,6 @@ namespace beast {
in_pos_ out_pos_ == 0
out_end_ == 0
*/
-//------------------------------------------------------------------------------
-
-template<class Allocator>
-class basic_multi_buffer<Allocator>::element
- : public boost::intrusive::list_base_hook<
- boost::intrusive::link_mode<
- boost::intrusive::normal_link>>
-{
- using size_type = typename
- detail::allocator_traits<Allocator>::size_type;
-
- size_type const size_;
-
-public:
- element(element const&) = delete;
-
- explicit
- element(size_type n) noexcept
- : size_(n)
- {
- }
-
- size_type
- size() const noexcept
- {
- return size_;
- }
-
- char*
- data() const noexcept
- {
- return const_cast<char*>(
- reinterpret_cast<char const*>(this + 1));
- }
-};
//------------------------------------------------------------------------------
@@ -487,7 +451,7 @@ template<class Allocator>
basic_multi_buffer<Allocator>::
basic_multi_buffer(
Allocator const& alloc) noexcept
- : boost::empty_value<base_alloc_type>(
+ : boost::empty_value<Allocator>(
boost::empty_init_t(), alloc)
, max_(alloc_traits::max_size(this->get()))
, out_(list_.end())
@@ -499,8 +463,8 @@ basic_multi_buffer<Allocator>::
basic_multi_buffer(
std::size_t limit,
Allocator const& alloc) noexcept
- : boost::empty_value<
- base_alloc_type>(boost::empty_init_t(), alloc)
+ : boost::empty_value<Allocator>(
+ boost::empty_init_t(), alloc)
, max_(limit)
, out_(list_.end())
{
@@ -510,7 +474,7 @@ template<class Allocator>
basic_multi_buffer<Allocator>::
basic_multi_buffer(
basic_multi_buffer&& other) noexcept
- : boost::empty_value<base_alloc_type>(
+ : boost::empty_value<Allocator>(
boost::empty_init_t(), std::move(other.get()))
, max_(other.max_)
, in_size_(boost::exchange(other.in_size_, 0))
@@ -529,9 +493,9 @@ template<class Allocator>
basic_multi_buffer<Allocator>::
basic_multi_buffer(
basic_multi_buffer&& other,
- Allocator const& alloc)
- : boost::empty_value<
- base_alloc_type>(boost::empty_init_t(), alloc)
+ Allocator const& alloc)
+ : boost::empty_value<Allocator>(
+ boost::empty_init_t(), alloc)
, max_(other.max_)
{
if(this->get() != other.get())
@@ -562,7 +526,7 @@ template<class Allocator>
basic_multi_buffer<Allocator>::
basic_multi_buffer(
basic_multi_buffer const& other)
- : boost::empty_value<base_alloc_type>(
+ : boost::empty_value<Allocator>(
boost::empty_init_t(), alloc_traits::
select_on_container_copy_construction(
other.get()))
@@ -577,7 +541,7 @@ basic_multi_buffer<Allocator>::
basic_multi_buffer(
basic_multi_buffer const& other,
Allocator const& alloc)
- : boost::empty_value<base_alloc_type>(
+ : boost::empty_value<Allocator>(
boost::empty_init_t(), alloc)
, max_(other.max_)
, out_(list_.end())
@@ -601,8 +565,8 @@ basic_multi_buffer<Allocator>::
basic_multi_buffer(
basic_multi_buffer<OtherAlloc> const& other,
allocator_type const& alloc)
- : boost::empty_value<
- base_alloc_type>(boost::empty_init_t(), alloc)
+ : boost::empty_value<Allocator>(
+ boost::empty_init_t(), alloc)
, max_(other.max_)
, out_(list_.end())
{
@@ -1012,10 +976,7 @@ consume(size_type n) noexcept
in_pos_ = 0;
auto& e = list_.front();
list_.erase(list_.iterator_to(e));
- auto const len = sizeof(e) + e.size();
- e.~element();
- alloc_traits::deallocate(this->get(),
- reinterpret_cast<char*>(&e), len);
+ destroy(e);
#if BOOST_BEAST_MULTI_BUFFER_DEBUG_CHECK
debug_check();
#endif
@@ -1216,10 +1177,14 @@ void
basic_multi_buffer<Allocator>::
destroy(element& e)
{
- auto const len = sizeof(e) + e.size();
+ auto a = rebind_type{this->get()};
+ auto const n =
+ (sizeof(element) + e.size() +
+ sizeof(align_type) - 1) /
+ sizeof(align_type);
e.~element();
- alloc_traits::deallocate(this->get(),
- reinterpret_cast<char*>(&e), len);
+ alloc_traits::deallocate(a,
+ reinterpret_cast<align_type*>(&e), n);
}
template<class Allocator>
@@ -1231,9 +1196,11 @@ alloc(std::size_t size) ->
if(size > alloc_traits::max_size(this->get()))
BOOST_THROW_EXCEPTION(std::length_error(
"A basic_multi_buffer exceeded the allocator's maximum size"));
- return *::new(alloc_traits::allocate(
- this->get(),
- sizeof(element) + size)) element(size);
+ auto a = rebind_type{this->get()};
+ auto const p = alloc_traits::allocate(a,
+ (sizeof(element) + size + sizeof(align_type) - 1) /
+ sizeof(align_type));
+ return *(::new(p) element(size));
}
template<class Allocator>
diff --git a/boost/beast/core/impl/read_size.hpp b/boost/beast/core/impl/read_size.hpp
index 1896c014b8..babbcaac11 100644
--- a/boost/beast/core/impl/read_size.hpp
+++ b/boost/beast/core/impl/read_size.hpp
@@ -46,7 +46,6 @@ read_size(DynamicBuffer& buffer,
static_assert(
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
- BOOST_ASSERT(max_size >= 1);
auto const size = buffer.size();
auto const limit = buffer.max_size() - size;
BOOST_ASSERT(size <= buffer.max_size());
diff --git a/boost/beast/core/impl/static_buffer.hpp b/boost/beast/core/impl/static_buffer.hpp
index dee13bfbe5..ae4f53c1b5 100644
--- a/boost/beast/core/impl/static_buffer.hpp
+++ b/boost/beast/core/impl/static_buffer.hpp
@@ -10,12 +10,7 @@
#ifndef BOOST_BEAST_IMPL_STATIC_BUFFER_HPP
#define BOOST_BEAST_IMPL_STATIC_BUFFER_HPP
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
-#include <boost/throw_exception.hpp>
-#include <algorithm>
-#include <cstring>
-#include <iterator>
#include <stdexcept>
namespace boost {
diff --git a/boost/beast/core/impl/static_buffer.ipp b/boost/beast/core/impl/static_buffer.ipp
index c26ff429b8..b87d704b65 100644
--- a/boost/beast/core/impl/static_buffer.ipp
+++ b/boost/beast/core/impl/static_buffer.ipp
@@ -11,12 +11,8 @@
#define BOOST_BEAST_IMPL_STATIC_BUFFER_IPP
#include <boost/beast/core/static_buffer.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/throw_exception.hpp>
-#include <algorithm>
-#include <cstring>
-#include <iterator>
#include <stdexcept>
namespace boost {
diff --git a/boost/beast/core/impl/static_string.hpp b/boost/beast/core/impl/static_string.hpp
index c668b837fa..2e3e5617ab 100644
--- a/boost/beast/core/impl/static_string.hpp
+++ b/boost/beast/core/impl/static_string.hpp
@@ -11,7 +11,6 @@
#define BOOST_BEAST_IMPL_STATIC_STRING_HPP
#include <boost/beast/core/detail/static_string.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/throw_exception.hpp>
namespace boost {
@@ -559,64 +558,6 @@ assign_char(CharT, std::false_type) ->
"max_size() == 0"});
}
-namespace detail {
-
-template<class Integer>
-static_string<max_digits(sizeof(Integer))>
-to_static_string(Integer x, std::true_type)
-{
- if(x == 0)
- return {'0'};
- static_string<detail::max_digits(
- sizeof(Integer))> s;
- if(x < 0)
- {
- x = -x;
- char buf[max_digits(sizeof(x))];
- char* p = buf;
- for(;x > 0; x /= 10)
- *p++ = "0123456789"[x % 10];
- s.resize(1 + p - buf);
- s[0] = '-';
- auto d = &s[1];
- while(p > buf)
- *d++ = *--p;
- }
- else
- {
- char buf[max_digits(sizeof(x))];
- char* p = buf;
- for(;x > 0; x /= 10)
- *p++ = "0123456789"[x % 10];
- s.resize(p - buf);
- auto d = &s[0];
- while(p > buf)
- *d++ = *--p;
- }
- return s;
-}
-
-template<class Integer>
-static_string<max_digits(sizeof(Integer))>
-to_static_string(Integer x, std::false_type)
-{
- if(x == 0)
- return {'0'};
- char buf[max_digits(sizeof(x))];
- char* p = buf;
- for(;x > 0; x /= 10)
- *p++ = "0123456789"[x % 10];
- static_string<detail::max_digits(
- sizeof(Integer))> s;
- s.resize(p - buf);
- auto d = &s[0];
- while(p > buf)
- *d++ = *--p;
- return s;
-}
-
-} // detail
-
template<class Integer, class>
static_string<detail::max_digits(sizeof(Integer))>
to_static_string(Integer x)
diff --git a/boost/beast/core/impl/string.ipp b/boost/beast/core/impl/string.ipp
new file mode 100644
index 0000000000..b64ce3f6aa
--- /dev/null
+++ b/boost/beast/core/impl/string.ipp
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_IMPL_STRING_IPP
+#define BOOST_BEAST_IMPL_STRING_IPP
+
+#include <boost/beast/core/string.hpp>
+#include <boost/beast/core/detail/string.hpp>
+
+#include <algorithm>
+
+namespace boost {
+namespace beast {
+
+bool
+iequals(
+ beast::string_view lhs,
+ beast::string_view rhs)
+{
+ auto n = lhs.size();
+ if(rhs.size() != n)
+ return false;
+ auto p1 = lhs.data();
+ auto p2 = rhs.data();
+ char a, b;
+ // fast loop
+ while(n--)
+ {
+ a = *p1++;
+ b = *p2++;
+ if(a != b)
+ goto slow;
+ }
+ return true;
+slow:
+ do
+ {
+ if( detail::ascii_tolower(a) !=
+ detail::ascii_tolower(b))
+ return false;
+ a = *p1++;
+ b = *p2++;
+ }
+ while(n--);
+ return true;
+}
+
+bool
+iless::operator()(
+ string_view lhs,
+ string_view rhs) const
+{
+ using std::begin;
+ using std::end;
+ return std::lexicographical_compare(
+ begin(lhs), end(lhs), begin(rhs), end(rhs),
+ [](char c1, char c2)
+ {
+ return detail::ascii_tolower(c1) < detail::ascii_tolower(c2);
+ }
+ );
+}
+
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/core/multi_buffer.hpp b/boost/beast/core/multi_buffer.hpp
index 2cf477a83b..837310c004 100644
--- a/boost/beast/core/multi_buffer.hpp
+++ b/boost/beast/core/multi_buffer.hpp
@@ -15,6 +15,7 @@
#include <boost/asio/buffer.hpp>
#include <boost/core/empty_value.hpp>
#include <boost/intrusive/list.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
#include <iterator>
#include <limits>
#include <memory>
@@ -62,14 +63,13 @@ namespace beast {
template<class Allocator>
class basic_multi_buffer
#if ! BOOST_BEAST_DOXYGEN
- : private boost::empty_value<
- typename detail::allocator_traits<Allocator>::
- template rebind_alloc<char>>
+ : private boost::empty_value<Allocator>
#endif
{
- using base_alloc_type = typename
- detail::allocator_traits<Allocator>::
- template rebind_alloc<char>;
+ // Fancy pointers are not supported
+ static_assert(std::is_pointer<typename
+ std::allocator_traits<Allocator>::pointer>::value,
+ "Allocator must use regular pointers");
static bool constexpr default_nothrow =
std::is_nothrow_default_constructible<Allocator>::value;
@@ -77,19 +77,61 @@ class basic_multi_buffer
// Storage for the list of buffers representing the input
// and output sequences. The allocation for each element
// contains `element` followed by raw storage bytes.
- class element;
+ class element
+ : public boost::intrusive::list_base_hook<
+ boost::intrusive::link_mode<
+ boost::intrusive::normal_link>>
+ {
+ using size_type = typename
+ detail::allocator_traits<Allocator>::size_type;
+
+ size_type const size_;
+
+ public:
+ element(element const&) = delete;
+
+ explicit
+ element(size_type n) noexcept
+ : size_(n)
+ {
+ }
+
+ size_type
+ size() const noexcept
+ {
+ return size_;
+ }
+
+ char*
+ data() const noexcept
+ {
+ return const_cast<char*>(
+ reinterpret_cast<char const*>(this + 1));
+ }
+ };
template<bool>
class readable_bytes;
+ using size_type = typename
+ detail::allocator_traits<Allocator>::size_type;
+
+ using align_type = typename
+ boost::type_with_alignment<alignof(element)>::type;
+
+ using rebind_type = typename
+ beast::detail::allocator_traits<Allocator>::
+ template rebind_alloc<align_type>;
+
using alloc_traits =
- beast::detail::allocator_traits<base_alloc_type>;
- using list_type = typename boost::intrusive::make_list<element,
- boost::intrusive::constant_time_size<true>>::type;
+ beast::detail::allocator_traits<rebind_type>;
+
+ using list_type = typename boost::intrusive::make_list<
+ element, boost::intrusive::constant_time_size<true>>::type;
+
using iter = typename list_type::iterator;
- using const_iter = typename list_type::const_iterator;
- using size_type = typename alloc_traits::size_type;
+ using const_iter = typename list_type::const_iterator;
using pocma = typename
alloc_traits::propagate_on_container_move_assignment;
diff --git a/boost/beast/core/rate_policy.hpp b/boost/beast/core/rate_policy.hpp
index 1f8abb9b6a..6375b11811 100644
--- a/boost/beast/core/rate_policy.hpp
+++ b/boost/beast/core/rate_policy.hpp
@@ -152,7 +152,7 @@ class simple_rate_policy
friend class rate_policy_access;
static std::size_t constexpr all =
- std::numeric_limits<std::size_t>::max();
+ (std::numeric_limits<std::size_t>::max)();
std::size_t rd_remain_ = all;
std::size_t wr_remain_ = all;
diff --git a/boost/beast/core/span.hpp b/boost/beast/core/span.hpp
index e170729472..55a1454efd 100644
--- a/boost/beast/core/span.hpp
+++ b/boost/beast/core/span.hpp
@@ -186,21 +186,21 @@ public:
{
return data_;
}
-
+
/// Returns an iterator to the beginning of the span
const_iterator
cbegin() const
{
return data_;
}
-
+
/// Returns an iterator to one past the end of the span
const_iterator
end() const
{
return data_ + size_;
}
-
+
/// Returns an iterator to one past the end of the span
const_iterator
cend() const
diff --git a/boost/beast/core/static_buffer.hpp b/boost/beast/core/static_buffer.hpp
index 1e44237164..c4ff534f56 100644
--- a/boost/beast/core/static_buffer.hpp
+++ b/boost/beast/core/static_buffer.hpp
@@ -13,11 +13,7 @@
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/detail/buffers_pair.hpp>
#include <boost/asio/buffer.hpp>
-#include <boost/assert.hpp>
-#include <algorithm>
-#include <array>
#include <cstddef>
-#include <cstring>
namespace boost {
namespace beast {
@@ -134,7 +130,7 @@ public:
BOOST_BEAST_DECL
const_buffers_type
data() const noexcept;
-
+
/// Returns a constant buffer sequence representing the readable bytes
const_buffers_type
cdata() const noexcept
@@ -148,7 +144,7 @@ public:
data() noexcept;
/** Returns a mutable buffer sequence representing writable bytes.
-
+
Returns a mutable buffer sequence representing the writable
bytes containing exactly `n` bytes of storage. Memory may be
reallocated as needed.
diff --git a/boost/beast/core/static_string.hpp b/boost/beast/core/static_string.hpp
index fc60a72e7d..c1cea6c36e 100644
--- a/boost/beast/core/static_string.hpp
+++ b/boost/beast/core/static_string.hpp
@@ -16,8 +16,7 @@
#include <algorithm>
#include <cstdint>
#include <initializer_list>
-#include <iterator>
-#include <ostream>
+#include <iosfwd>
#include <stdexcept>
#include <string>
#include <type_traits>
diff --git a/boost/beast/core/string.hpp b/boost/beast/core/string.hpp
index 976bfca48a..06edca1969 100644
--- a/boost/beast/core/string.hpp
+++ b/boost/beast/core/string.hpp
@@ -11,82 +11,11 @@
#define BOOST_BEAST_STRING_HPP
#include <boost/beast/core/detail/config.hpp>
-#include <boost/version.hpp>
-
-#if defined(BOOST_BEAST_USE_STD_STRING_VIEW)
-#include <string_view>
-#else
-#include <boost/utility/string_view.hpp>
-#endif
-
-#include <algorithm>
+#include <boost/beast/core/string_type.hpp>
namespace boost {
namespace beast {
-#if defined(BOOST_BEAST_USE_STD_STRING_VIEW)
- /// The type of string view used by the library
- using string_view = std::string_view;
-
- /// The type of basic string view used by the library
- template<class CharT, class Traits>
- using basic_string_view =
- std::basic_string_view<CharT, Traits>;
-#else
- /// The type of string view used by the library
- using string_view = boost::string_view;
-
- /// The type of basic string view used by the library
- template<class CharT, class Traits>
- using basic_string_view =
- boost::basic_string_view<CharT, Traits>;
-#endif
-
-namespace detail {
-
-inline
-char
-ascii_tolower(char c)
-{
- return ((static_cast<unsigned>(c) - 65U) < 26) ?
- c + 'a' - 'A' : c;
-}
-
-template<class = void>
-bool
-iequals(
- beast::string_view lhs,
- beast::string_view rhs)
-{
- auto n = lhs.size();
- if(rhs.size() != n)
- return false;
- auto p1 = lhs.data();
- auto p2 = rhs.data();
- char a, b;
- // fast loop
- while(n--)
- {
- a = *p1++;
- b = *p2++;
- if(a != b)
- goto slow;
- }
- return true;
-slow:
- do
- {
- if(ascii_tolower(a) != ascii_tolower(b))
- return false;
- a = *p1++;
- b = *p2++;
- }
- while(n--);
- return true;
-}
-
-} // detail
-
/** Returns `true` if two strings are equal, using a case-insensitive comparison.
The case-comparison operation is defined only for low-ASCII characters.
@@ -95,14 +24,11 @@ slow:
@param rhs The string on the right side of the equality
*/
-inline
+BOOST_BEAST_DECL
bool
iequals(
beast::string_view lhs,
- beast::string_view rhs)
-{
- return detail::iequals(lhs, rhs);
-}
+ beast::string_view rhs);
/** A case-insensitive less predicate for strings.
@@ -110,21 +36,11 @@ iequals(
*/
struct iless
{
+ BOOST_BEAST_DECL
bool
operator()(
string_view lhs,
- string_view rhs) const
- {
- using std::begin;
- using std::end;
- return std::lexicographical_compare(
- begin(lhs), end(lhs), begin(rhs), end(rhs),
- [](char c1, char c2)
- {
- return detail::ascii_tolower(c1) < detail::ascii_tolower(c2);
- }
- );
- }
+ string_view rhs) const;
};
/** A case-insensitive equality predicate for strings.
@@ -145,4 +61,8 @@ struct iequal
} // beast
} // boost
+#ifdef BOOST_BEAST_HEADER_ONLY
+#include <boost/beast/core/impl/string.ipp>
+#endif
+
#endif
diff --git a/boost/beast/core/string_param.hpp b/boost/beast/core/string_param.hpp
index 67ef69469c..cc55bfd170 100644
--- a/boost/beast/core/string_param.hpp
+++ b/boost/beast/core/string_param.hpp
@@ -14,7 +14,6 @@
#include <boost/beast/core/string.hpp>
#include <boost/beast/core/static_string.hpp>
#include <boost/beast/core/detail/static_ostream.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/optional.hpp>
namespace boost {
diff --git a/boost/beast/core/string_type.hpp b/boost/beast/core/string_type.hpp
new file mode 100644
index 0000000000..b6b3f00534
--- /dev/null
+++ b/boost/beast/core/string_type.hpp
@@ -0,0 +1,45 @@
+//
+// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_STRING_TYPE_HPP
+#define BOOST_BEAST_STRING_TYPE_HPP
+
+#include <boost/beast/core/detail/config.hpp>
+
+#if defined(BOOST_BEAST_USE_STD_STRING_VIEW)
+#include <string_view>
+#else
+#include <boost/utility/string_view.hpp>
+#endif
+
+namespace boost {
+namespace beast {
+
+#if BOOST_BEAST_DOXYGEN || ! defined(BOOST_BEAST_USE_STD_STRING_VIEW)
+/// The type of string view used by the library
+using string_view = boost::string_view;
+
+/// The type of `basic_string_view` used by the library
+template<class CharT, class Traits>
+using basic_string_view =
+ boost::basic_string_view<CharT, Traits>;
+
+#else
+using string_view = std::string_view;
+
+template<class CharT, class Traits>
+using basic_string_view =
+ std::basic_string_view<CharT, Traits>;
+
+#endif
+
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/http/basic_dynamic_body.hpp b/boost/beast/http/basic_dynamic_body.hpp
index 3fea37379b..f49c50daf8 100644
--- a/boost/beast/http/basic_dynamic_body.hpp
+++ b/boost/beast/http/basic_dynamic_body.hpp
@@ -13,6 +13,7 @@
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/core/detail/buffer.hpp>
+#include <boost/beast/core/detail/clamp.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/optional.hpp>
@@ -89,7 +90,7 @@ struct basic_dynamic_body
error_code& ec)
{
auto const n = buffer_bytes(buffers);
- if(body_.size() > body_.max_size() - n)
+ if(beast::detail::sum_exceeds(body_.size(), n, body_.max_size()))
{
ec = error::buffer_overflow;
return 0;
diff --git a/boost/beast/http/detail/basic_parser.hpp b/boost/beast/http/detail/basic_parser.hpp
index f4e9083ffa..196d1c0a28 100644
--- a/boost/beast/http/detail/basic_parser.hpp
+++ b/boost/beast/http/detail/basic_parser.hpp
@@ -10,8 +10,8 @@
#ifndef BOOST_BEAST_HTTP_DETAIL_BASIC_PARSER_HPP
#define BOOST_BEAST_HTTP_DETAIL_BASIC_PARSER_HPP
-#include <boost/beast/core/static_string.hpp>
#include <boost/beast/core/string.hpp>
+#include <boost/beast/core/detail/char_buffer.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/detail/rfc7230.hpp>
#include <boost/config.hpp>
@@ -127,7 +127,7 @@ struct basic_parser_base
BOOST_BEAST_DECL
static
bool
- parse_dec(char const* it, char const* last, std::uint64_t& v);
+ parse_dec(string_view s, std::uint64_t& v);
BOOST_BEAST_DECL
static
@@ -182,7 +182,7 @@ struct basic_parser_base
char const* last,
string_view& name,
string_view& value,
- static_string<max_obs_fold>& buf,
+ beast::detail::char_buffer<max_obs_fold>& buf,
error_code& ec);
BOOST_BEAST_DECL
diff --git a/boost/beast/http/detail/basic_parser.ipp b/boost/beast/http/detail/basic_parser.ipp
index 934d0dc505..5dd13d4ce1 100644
--- a/boost/beast/http/detail/basic_parser.ipp
+++ b/boost/beast/http/detail/basic_parser.ipp
@@ -154,8 +154,12 @@ find_eol(
bool
basic_parser_base::
-parse_dec(char const* it, char const* last, std::uint64_t& v)
+parse_dec(
+ string_view s,
+ std::uint64_t& v)
{
+ char const* it = s.data();
+ char const* last = it + s.size();
if(it == last)
return false;
std::uint64_t tmp = 0;
@@ -491,7 +495,7 @@ parse_field(
char const* last,
string_view& name,
string_view& value,
- static_string<max_obs_fold>& buf,
+ beast::detail::char_buffer<max_obs_fold>& buf,
error_code& ec)
{
/* header-field = field-name ":" OWS field-value OWS
@@ -607,63 +611,60 @@ parse_field(
if(token_last != first)
break;
}
- buf.resize(0);
- buf.append(first, token_last);
+ buf.clear();
+ if (!buf.try_append(first, token_last))
+ {
+ ec = error::header_limit;
+ return;
+ }
+
BOOST_ASSERT(! buf.empty());
-#ifndef BOOST_NO_EXCEPTIONS
- try
-#endif
+ for(;;)
{
- for(;;)
+ // eat leading ' ' and '\t'
+ for(;;++p)
{
- // eat leading ' ' and '\t'
- for(;;++p)
- {
- if(p + 1 > last)
- {
- ec = error::need_more;
- return;
- }
- if(! (*p == ' ' || *p == '\t'))
- break;
- }
- // parse to CRLF
- first = p;
- p = parse_token_to_eol(p, last, token_last, ec);
- if(ec)
- return;
- if(! p)
- {
- ec = error::bad_value;
- return;
- }
- // Look 1 char past the CRLF to handle obs-fold.
if(p + 1 > last)
{
ec = error::need_more;
return;
}
- token_last = trim_back(token_last, first);
- if(first != token_last)
- {
- buf.push_back(' ');
- buf.append(first, token_last);
- }
- if(*p != ' ' && *p != '\t')
+ if(! (*p == ' ' || *p == '\t'))
+ break;
+ }
+ // parse to CRLF
+ first = p;
+ p = parse_token_to_eol(p, last, token_last, ec);
+ if(ec)
+ return;
+ if(! p)
+ {
+ ec = error::bad_value;
+ return;
+ }
+ // Look 1 char past the CRLF to handle obs-fold.
+ if(p + 1 > last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ token_last = trim_back(token_last, first);
+ if(first != token_last)
+ {
+ if (!buf.try_push_back(' ') ||
+ !buf.try_append(first, token_last))
{
- value = {buf.data(), buf.size()};
+ ec = error::header_limit;
return;
}
- ++p;
}
+ if(*p != ' ' && *p != '\t')
+ {
+ value = {buf.data(), buf.size()};
+ return;
+ }
+ ++p;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(std::length_error const&)
- {
- ec = error::header_limit;
- return;
- }
-#endif
}
diff --git a/boost/beast/http/detail/rfc7230.hpp b/boost/beast/http/detail/rfc7230.hpp
index 99f4af05e1..35bed0ab22 100644
--- a/boost/beast/http/detail/rfc7230.hpp
+++ b/boost/beast/http/detail/rfc7230.hpp
@@ -57,14 +57,6 @@ std::int8_t
unhex(char c);
BOOST_BEAST_DECL
-void
-skip_ows(char const*& it, char const* end);
-
-BOOST_BEAST_DECL
-void
-skip_token(char const*& it, char const* last);
-
-BOOST_BEAST_DECL
string_view
trim(string_view s);
diff --git a/boost/beast/http/detail/rfc7230.ipp b/boost/beast/http/detail/rfc7230.ipp
index 612eaf9a02..4d69e77241 100644
--- a/boost/beast/http/detail/rfc7230.ipp
+++ b/boost/beast/http/detail/rfc7230.ipp
@@ -219,8 +219,9 @@ unhex(char c)
return tab[static_cast<unsigned char>(c)];
}
+template <class ForwardIt>
void
-skip_ows(char const*& it, char const* end)
+skip_ows(ForwardIt& it, ForwardIt end)
{
while(it != end)
{
@@ -230,8 +231,9 @@ skip_ows(char const*& it, char const* end)
}
}
+template <class ForwardIt>
void
-skip_token(char const*& it, char const* last)
+skip_token(ForwardIt& it, ForwardIt last)
{
while(it != last && is_token_char(*it))
++it;
diff --git a/boost/beast/http/fields.hpp b/boost/beast/http/fields.hpp
index 927191d755..24b1a12203 100644
--- a/boost/beast/http/fields.hpp
+++ b/boost/beast/http/fields.hpp
@@ -62,8 +62,6 @@ class basic_fields
friend class fields_test; // for `header`
- static std::size_t constexpr max_static_buffer = 4096;
-
struct element;
using off_t = std::uint16_t;
@@ -72,7 +70,7 @@ public:
/// The type of allocator used.
using allocator_type = Allocator;
- /// The type of element used to represent a field
+ /// The type of element used to represent a field
class value_type
{
friend class basic_fields;
@@ -198,7 +196,7 @@ private:
using rebind_type = typename
beast::detail::allocator_traits<Allocator>::
- template rebind_alloc<element>;
+ template rebind_alloc<align_type>;
using alloc_traits =
beast::detail::allocator_traits<rebind_type>;
diff --git a/boost/beast/http/impl/basic_parser.ipp b/boost/beast/http/impl/basic_parser.ipp
index 99947ae1f2..5cab22a884 100644
--- a/boost/beast/http/impl/basic_parser.ipp
+++ b/boost/beast/http/impl/basic_parser.ipp
@@ -14,9 +14,9 @@
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/rfc7230.hpp>
#include <boost/beast/core/buffer_traits.hpp>
-#include <boost/beast/core/static_string.hpp>
#include <boost/beast/core/detail/clamp.hpp>
#include <boost/beast/core/detail/config.hpp>
+#include <boost/beast/core/detail/string.hpp>
#include <boost/asio/buffer.hpp>
#include <algorithm>
#include <utility>
@@ -405,7 +405,7 @@ parse_fields(char const*& in,
string_view name;
string_view value;
// https://stackoverflow.com/questions/686217/maximum-on-http-header-values
- static_string<max_obs_fold> buf;
+ beast::detail::char_buffer<max_obs_fold> buf;
auto p = in;
for(;;)
{
@@ -508,15 +508,16 @@ finish_header(error_code& ec, std::false_type)
}
else if(f_ & flagContentLength)
{
- if(len_ > body_limit_)
- {
- ec = error::body_limit;
- return;
- }
if(len_ > 0)
{
f_ |= flagHasBody;
state_ = state::body0;
+
+ if(len_ > body_limit_)
+ {
+ ec = error::body_limit;
+ return;
+ }
}
else
{
@@ -746,6 +747,7 @@ basic_parser<isRequest>::
do_field(field f,
string_view value, error_code& ec)
{
+ using namespace beast::detail::string_literals;
// Connection
if(f == field::connection ||
f == field::proxy_connection)
@@ -759,19 +761,19 @@ do_field(field f,
}
for(auto const& s : list)
{
- if(iequals({"close", 5}, s))
+ if(beast::iequals("close"_sv, s))
{
f_ |= flagConnectionClose;
continue;
}
- if(iequals({"keep-alive", 10}, s))
+ if(beast::iequals("keep-alive"_sv, s))
{
f_ |= flagConnectionKeepAlive;
continue;
}
- if(iequals({"upgrade", 7}, s))
+ if(beast::iequals("upgrade"_sv, s))
{
f_ |= flagConnectionUpgrade;
continue;
@@ -799,8 +801,7 @@ do_field(field f,
}
std::uint64_t v;
- if(! parse_dec(
- value.begin(), value.end(), v))
+ if(! parse_dec(value, v))
{
ec = error::bad_content_length;
return;
@@ -833,9 +834,9 @@ do_field(field f,
ec = {};
auto const v = token_list{value};
auto const p = std::find_if(v.begin(), v.end(),
- [&](typename token_list::value_type const& s)
+ [&](string_view const& s)
{
- return iequals({"chunked", 7}, s);
+ return beast::iequals("chunked"_sv, s);
});
if(p == v.end())
return;
diff --git a/boost/beast/http/impl/fields.hpp b/boost/beast/http/impl/fields.hpp
index 9616af829c..2711df38b4 100644
--- a/boost/beast/http/impl/fields.hpp
+++ b/boost/beast/http/impl/fields.hpp
@@ -12,9 +12,9 @@
#include <boost/beast/core/buffers_cat.hpp>
#include <boost/beast/core/string.hpp>
-#include <boost/beast/core/static_string.hpp>
#include <boost/beast/core/detail/buffers_ref.hpp>
#include <boost/beast/core/detail/clamp.hpp>
+#include <boost/beast/core/detail/temporary_buffer.hpp>
#include <boost/beast/http/verb.hpp>
#include <boost/beast/http/rfc7230.hpp>
#include <boost/beast/http/status.hpp>
@@ -24,13 +24,6 @@
#include <stdexcept>
#include <string>
-#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
- // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
-#ifndef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
-#define BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
-#endif
-#endif
-
namespace boost {
namespace beast {
namespace http {
@@ -584,7 +577,7 @@ insert(field name,
}
auto const last = std::prev(before);
// VFALCO is it worth comparing `field name` first?
- if(! iequals(sname, last->name_string()))
+ if(! beast::iequals(sname, last->name_string()))
{
BOOST_ASSERT(count(sname) == 0);
set_.insert_before(before, e);
@@ -751,136 +744,31 @@ equal_range(string_view name) const ->
namespace detail {
-// Filter a token list
-//
-template<class String, class Pred>
-void
-filter_token_list(
- String& s,
- string_view value,
- Pred&& pred)
+struct iequals_predicate
{
- token_list te{value};
- auto it = te.begin();
- auto last = te.end();
- if(it == last)
- return;
- while(pred(*it))
- if(++it == last)
- return;
- s.append(it->data(), it->size());
- while(++it != last)
+ bool
+ operator()(string_view s) const
{
- if(! pred(*it))
- {
- s.append(", ");
- s.append(it->data(), it->size());
- }
+ return beast::iequals(s, sv1) || beast::iequals(s, sv2);
}
-}
+
+ string_view sv1;
+ string_view sv2;
+};
// Filter the last item in a token list
-template<class String, class Pred>
+BOOST_BEAST_DECL
void
filter_token_list_last(
- String& s,
+ beast::detail::temporary_buffer& s,
string_view value,
- Pred&& pred)
-{
- token_list te{value};
- if(te.begin() != te.end())
- {
- auto it = te.begin();
- auto next = std::next(it);
- if(next == te.end())
- {
- if(! pred(*it))
- s.append(it->data(), it->size());
- return;
- }
- s.append(it->data(), it->size());
- for(;;)
- {
- it = next;
- next = std::next(it);
- if(next == te.end())
- {
- if(! pred(*it))
- {
- s.append(", ");
- s.append(it->data(), it->size());
- }
- return;
- }
- s.append(", ");
- s.append(it->data(), it->size());
- }
- }
-}
+ iequals_predicate const& pred);
-template<class String>
+BOOST_BEAST_DECL
void
keep_alive_impl(
- String& s, string_view value,
- unsigned version, bool keep_alive)
-{
- if(version < 11)
- {
- if(keep_alive)
- {
- // remove close
- filter_token_list(s, value,
- [](string_view s)
- {
- return iequals(s, "close");
- });
- // add keep-alive
- if(s.empty())
- s.append("keep-alive");
- else if(! token_list{value}.exists("keep-alive"))
- s.append(", keep-alive");
- }
- else
- {
- // remove close and keep-alive
- filter_token_list(s, value,
- [](string_view s)
- {
- return
- iequals(s, "close") ||
- iequals(s, "keep-alive");
- });
- }
- }
- else
- {
- if(keep_alive)
- {
- // remove close and keep-alive
- filter_token_list(s, value,
- [](string_view s)
- {
- return
- iequals(s, "close") ||
- iequals(s, "keep-alive");
- });
- }
- else
- {
- // remove keep-alive
- filter_token_list(s, value,
- [](string_view s)
- {
- return iequals(s, "keep-alive");
- });
- // add close
- if(s.empty())
- s.append("close");
- else if(! token_list{value}.exists("close"))
- s.append(", close");
- }
- }
-}
+ beast::detail::temporary_buffer& s, string_view value,
+ unsigned version, bool keep_alive);
} // detail
@@ -930,7 +818,7 @@ get_chunked_impl() const
{
auto const next = std::next(it);
if(next == te.end())
- return iequals(*it, "chunked");
+ return beast::iequals(*it, "chunked");
it = next;
}
return false;
@@ -997,6 +885,7 @@ void
basic_fields<Allocator>::
set_chunked_impl(bool value)
{
+ beast::detail::temporary_buffer buf;
auto it = find(field::transfer_encoding);
if(value)
{
@@ -1012,84 +901,26 @@ set_chunked_impl(bool value)
auto const next = std::next(itt);
if(next == te.end())
{
- if(iequals(*itt, "chunked"))
+ if(beast::iequals(*itt, "chunked"))
return; // already set
break;
}
itt = next;
}
- static_string<max_static_buffer> buf;
- if(! beast::detail::sum_exceeds(
- it->value().size(), 9u, buf.max_size()))
- {
- buf.append(it->value().data(), it->value().size());
- buf.append(", chunked", 9);
- set(field::transfer_encoding, buf);
- }
- else
- {
- #ifdef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
- // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
- std::string s;
- #else
- using A =
- typename beast::detail::allocator_traits<
- Allocator>::template rebind_alloc<char>;
- std::basic_string<
- char,
- std::char_traits<char>,
- A> s{A{this->get()}};
- #endif
- s.reserve(it->value().size() + 9);
- s.append(it->value().data(), it->value().size());
- s.append(", chunked", 9);
- set(field::transfer_encoding, s);
- }
+
+ buf.append(it->value(), ", chunked");
+ set(field::transfer_encoding, buf.view());
return;
}
// filter "chunked"
if(it == end())
return;
-#ifndef BOOST_NO_EXCEPTIONS
- try
- {
- static_string<max_static_buffer> buf;
- detail::filter_token_list_last(buf, it->value(),
- [](string_view s)
- {
- return iequals(s, "chunked");
- });
- if(! buf.empty())
- set(field::transfer_encoding, buf);
- else
- erase(field::transfer_encoding);
- }
- catch(std::length_error const&)
-#endif
- {
- #ifdef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
- // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
- std::string s;
- #else
- using A =
- typename beast::detail::allocator_traits<
- Allocator>::template rebind_alloc<char>;
- std::basic_string<
- char,
- std::char_traits<char>,
- A> s{A{this->get()}};
- #endif
- s.reserve(it->value().size());
- detail::filter_token_list_last(s, it->value(),
- [](string_view s)
- {
- return iequals(s, "chunked");
- });
- if(! s.empty())
- set(field::transfer_encoding, s);
- else
- erase(field::transfer_encoding);
- }
+
+ detail::filter_token_list_last(buf, it->value(), {"chunked", {}});
+ if(! buf.empty())
+ set(field::transfer_encoding, buf.view());
+ else
+ erase(field::transfer_encoding);
}
template<class Allocator>
@@ -1112,40 +943,12 @@ set_keep_alive_impl(
{
// VFALCO What about Proxy-Connection ?
auto const value = (*this)[field::connection];
-#ifndef BOOST_NO_EXCEPTIONS
- try
- {
- static_string<max_static_buffer> buf;
- detail::keep_alive_impl(
- buf, value, version, keep_alive);
- if(buf.empty())
- erase(field::connection);
- else
- set(field::connection, buf);
- }
- catch(std::length_error const&)
-#endif
- {
- #ifdef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
- // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
- std::string s;
- #else
- using A =
- typename beast::detail::allocator_traits<
- Allocator>::template rebind_alloc<char>;
- std::basic_string<
- char,
- std::char_traits<char>,
- A> s{A{this->get()}};
- #endif
- s.reserve(value.size());
- detail::keep_alive_impl(
- s, value, version, keep_alive);
- if(s.empty())
- erase(field::connection);
- else
- set(field::connection, s);
- }
+ beast::detail::temporary_buffer buf;
+ detail::keep_alive_impl(buf, value, version, keep_alive);
+ if(buf.empty())
+ erase(field::connection);
+ else
+ set(field::connection, buf.view());
}
//------------------------------------------------------------------------------
@@ -1187,8 +990,8 @@ delete_element(element& e)
(sizeof(element) + e.off_ + e.len_ + 2 + sizeof(align_type) - 1) /
sizeof(align_type);
e.~element();
- alloc_traits::deallocate(a, &e, n);
- //reinterpret_cast<align_type*>(&e), n);
+ alloc_traits::deallocate(a,
+ reinterpret_cast<align_type*>(&e), n);
}
template<class Allocator>
@@ -1198,7 +1001,7 @@ set_element(element& e)
{
auto it = set_.lower_bound(
e.name_string(), key_compare{});
- if(it == set_.end() || ! iequals(
+ if(it == set_.end() || ! beast::iequals(
e.name_string(), it->name_string()))
{
set_.insert_before(it, e);
@@ -1214,7 +1017,7 @@ set_element(element& e)
delete_element(*it);
it = next;
if(it == set_.end() ||
- ! iequals(e.name_string(), it->name_string()))
+ ! beast::iequals(e.name_string(), it->name_string()))
break;
}
set_.insert_before(it, e);
@@ -1402,4 +1205,8 @@ swap(basic_fields& other, std::false_type)
} // beast
} // boost
+#ifdef BOOST_BEAST_HEADER_ONLY
+#include <boost/beast/http/impl/fields.ipp>
+#endif
+
#endif
diff --git a/boost/beast/http/impl/fields.ipp b/boost/beast/http/impl/fields.ipp
new file mode 100644
index 0000000000..379d0a4d50
--- /dev/null
+++ b/boost/beast/http/impl/fields.ipp
@@ -0,0 +1,138 @@
+//
+// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_HTTP_IMPL_FIELDS_IPP
+#define BOOST_BEAST_HTTP_IMPL_FIELDS_IPP
+
+#include <boost/beast/http/fields.hpp>
+
+namespace boost {
+namespace beast {
+namespace http {
+namespace detail {
+
+// `basic_fields` assumes that `std::size_t` is larger than `uint16_t`, so we
+// verify it explicitly here, so that users that use split compilation don't
+// need to pay the (fairly small) price for this sanity check
+BOOST_STATIC_ASSERT((std::numeric_limits<std::size_t>::max)() >=
+ (std::numeric_limits<std::uint32_t>::max)());
+
+// Filter a token list
+//
+inline
+void
+filter_token_list(
+ beast::detail::temporary_buffer& s,
+ string_view value,
+ iequals_predicate const& pred)
+{
+ token_list te{value};
+ auto it = te.begin();
+ auto last = te.end();
+ if(it == last)
+ return;
+ while(pred(*it))
+ if(++it == last)
+ return;
+ s.append(*it);
+ while(++it != last)
+ {
+ if(! pred(*it))
+ {
+ s.append(", ", *it);
+ }
+ }
+}
+
+void
+filter_token_list_last(
+ beast::detail::temporary_buffer& s,
+ string_view value,
+ iequals_predicate const& pred)
+{
+ token_list te{value};
+ if(te.begin() != te.end())
+ {
+ auto it = te.begin();
+ auto next = std::next(it);
+ if(next == te.end())
+ {
+ if(! pred(*it))
+ s.append(*it);
+ return;
+ }
+ s.append(*it);
+ for(;;)
+ {
+ it = next;
+ next = std::next(it);
+ if(next == te.end())
+ {
+ if(! pred(*it))
+ {
+ s.append(", ", *it);
+ }
+ return;
+ }
+ s.append(", ", *it);
+ }
+ }
+}
+
+void
+keep_alive_impl(
+ beast::detail::temporary_buffer& s, string_view value,
+ unsigned version, bool keep_alive)
+{
+ if(version < 11)
+ {
+ if(keep_alive)
+ {
+ // remove close
+ filter_token_list(s, value, iequals_predicate{"close", {}});
+ // add keep-alive
+ if(s.empty())
+ s.append("keep-alive");
+ else if(! token_list{value}.exists("keep-alive"))
+ s.append(", keep-alive");
+ }
+ else
+ {
+ // remove close and keep-alive
+ filter_token_list(s, value,
+ iequals_predicate{"close", "keep-alive"});
+ }
+ }
+ else
+ {
+ if(keep_alive)
+ {
+ // remove close and keep-alive
+ filter_token_list(s, value,
+ iequals_predicate{"close", "keep-alive"});
+ }
+ else
+ {
+ // remove keep-alive
+ filter_token_list(s, value, iequals_predicate{"keep-alive", {}});
+ // add close
+ if(s.empty())
+ s.append("close");
+ else if(! token_list{value}.exists("close"))
+ s.append(", close");
+ }
+ }
+}
+
+} // detail
+} // http
+} // beast
+} // boost
+
+#endif // BOOST_BEAST_HTTP_IMPL_FIELDS_IPP
diff --git a/boost/beast/http/impl/file_body_win32.hpp b/boost/beast/http/impl/file_body_win32.hpp
index fc74c49772..cfeb5aaefd 100644
--- a/boost/beast/http/impl/file_body_win32.hpp
+++ b/boost/beast/http/impl/file_body_win32.hpp
@@ -16,6 +16,7 @@
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/beast/core/detail/clamp.hpp>
+#include <boost/beast/core/detail/is_invocable.hpp>
#include <boost/beast/http/serializer.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/basic_stream_socket.hpp>
diff --git a/boost/beast/http/impl/message.hpp b/boost/beast/http/impl/message.hpp
index 805d01f09a..4b101ad3b9 100644
--- a/boost/beast/http/impl/message.hpp
+++ b/boost/beast/http/impl/message.hpp
@@ -11,7 +11,6 @@
#define BOOST_BEAST_HTTP_IMPL_MESSAGE_HPP
#include <boost/beast/core/error.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
diff --git a/boost/beast/http/impl/read.hpp b/boost/beast/http/impl/read.hpp
index faea67eb25..ba265a57ed 100644
--- a/boost/beast/http/impl/read.hpp
+++ b/boost/beast/http/impl/read.hpp
@@ -62,8 +62,12 @@ parse_until(
// caller to distinguish an SSL short read which
// represents a safe connection closure, versus
// a closure with data loss.
- if(parser.got_some() && ! parser.is_done())
+ if( ec != net::error::operation_aborted &&
+ parser.got_some() && ! parser.is_done())
+ {
ec = error::partial_message;
+ }
+
return 0;
}
if(parser.is_done())
@@ -160,7 +164,7 @@ template<
class read_msg_op
: public beast::stable_async_base<
Handler, beast::executor_type<Stream>>
- , public net::coroutine
+ , public asio::coroutine
{
using parser_type =
parser<isRequest, Body, Allocator>;
diff --git a/boost/beast/http/impl/rfc7230.hpp b/boost/beast/http/impl/rfc7230.hpp
index 11e424b4d1..40e2fff040 100644
--- a/boost/beast/http/impl/rfc7230.hpp
+++ b/boost/beast/http/impl/rfc7230.hpp
@@ -244,27 +244,6 @@ cend() const ->
return const_iterator{s_.end(), s_.end()};
}
-template<class T>
-auto
-ext_list::
-find(T const& s) ->
- const_iterator
-{
- return std::find_if(begin(), end(),
- [&s](value_type const& v)
- {
- return iequals(s, v.first);
- });
-}
-
-template<class T>
-bool
-ext_list::
-exists(T const& s)
-{
- return find(s) != end();
-}
-
//------------------------------------------------------------------------------
@@ -378,19 +357,6 @@ cend() const ->
return const_iterator{s_.end(), s_.end()};
}
-template<class T>
-bool
-token_list::
-exists(T const& s)
-{
- return std::find_if(begin(), end(),
- [&s](value_type const& v)
- {
- return iequals(s, v);
- }
- ) != end();
-}
-
template<class Policy>
bool
validate_list(detail::basic_parsed_list<
diff --git a/boost/beast/http/impl/rfc7230.ipp b/boost/beast/http/impl/rfc7230.ipp
index cf60cefa36..6b46493ea3 100644
--- a/boost/beast/http/impl/rfc7230.ipp
+++ b/boost/beast/http/impl/rfc7230.ipp
@@ -11,6 +11,7 @@
#define BOOST_BEAST_HTTP_IMPL_RFC7230_IPP
#include <boost/beast/http/rfc7230.hpp>
+#include <algorithm>
namespace boost {
namespace beast {
@@ -123,6 +124,24 @@ increment()
}
}
+auto
+ext_list::
+find(string_view const& s) -> const_iterator
+{
+ return std::find_if(begin(), end(),
+ [&s](value_type const& v)
+ {
+ return beast::iequals(s, v.first);
+ });
+}
+
+bool
+ext_list::
+exists(string_view const& s)
+{
+ return find(s) != end();
+}
+
void
token_list::const_iterator::
increment()
@@ -169,6 +188,18 @@ increment()
}
}
+bool
+token_list::
+exists(string_view const& s)
+{
+ return std::find_if(begin(), end(),
+ [&s](value_type const& v)
+ {
+ return beast::iequals(s, v);
+ }
+ ) != end();
+}
+
} // http
} // beast
} // boost
diff --git a/boost/beast/http/impl/verb.ipp b/boost/beast/http/impl/verb.ipp
index 20ef47c551..988f1b9430 100644
--- a/boost/beast/http/impl/verb.ipp
+++ b/boost/beast/http/impl/verb.ipp
@@ -21,50 +21,51 @@ namespace http {
string_view
to_string(verb v)
{
+ using namespace beast::detail::string_literals;
switch(v)
{
- case verb::delete_: return "DELETE";
- case verb::get: return "GET";
- case verb::head: return "HEAD";
- case verb::post: return "POST";
- case verb::put: return "PUT";
- case verb::connect: return "CONNECT";
- case verb::options: return "OPTIONS";
- case verb::trace: return "TRACE";
-
- case verb::copy: return "COPY";
- case verb::lock: return "LOCK";
- case verb::mkcol: return "MKCOL";
- case verb::move: return "MOVE";
- case verb::propfind: return "PROPFIND";
- case verb::proppatch: return "PROPPATCH";
- case verb::search: return "SEARCH";
- case verb::unlock: return "UNLOCK";
- case verb::bind: return "BIND";
- case verb::rebind: return "REBIND";
- case verb::unbind: return "UNBIND";
- case verb::acl: return "ACL";
-
- case verb::report: return "REPORT";
- case verb::mkactivity: return "MKACTIVITY";
- case verb::checkout: return "CHECKOUT";
- case verb::merge: return "MERGE";
-
- case verb::msearch: return "M-SEARCH";
- case verb::notify: return "NOTIFY";
- case verb::subscribe: return "SUBSCRIBE";
- case verb::unsubscribe: return "UNSUBSCRIBE";
-
- case verb::patch: return "PATCH";
- case verb::purge: return "PURGE";
-
- case verb::mkcalendar: return "MKCALENDAR";
-
- case verb::link: return "LINK";
- case verb::unlink: return "UNLINK";
-
+ case verb::delete_: return "DELETE"_sv;
+ case verb::get: return "GET"_sv;
+ case verb::head: return "HEAD"_sv;
+ case verb::post: return "POST"_sv;
+ case verb::put: return "PUT"_sv;
+ case verb::connect: return "CONNECT"_sv;
+ case verb::options: return "OPTIONS"_sv;
+ case verb::trace: return "TRACE"_sv;
+
+ case verb::copy: return "COPY"_sv;
+ case verb::lock: return "LOCK"_sv;
+ case verb::mkcol: return "MKCOL"_sv;
+ case verb::move: return "MOVE"_sv;
+ case verb::propfind: return "PROPFIND"_sv;
+ case verb::proppatch: return "PROPPATCH"_sv;
+ case verb::search: return "SEARCH"_sv;
+ case verb::unlock: return "UNLOCK"_sv;
+ case verb::bind: return "BIND"_sv;
+ case verb::rebind: return "REBIND"_sv;
+ case verb::unbind: return "UNBIND"_sv;
+ case verb::acl: return "ACL"_sv;
+
+ case verb::report: return "REPORT"_sv;
+ case verb::mkactivity: return "MKACTIVITY"_sv;
+ case verb::checkout: return "CHECKOUT"_sv;
+ case verb::merge: return "MERGE"_sv;
+
+ case verb::msearch: return "M-SEARCH"_sv;
+ case verb::notify: return "NOTIFY"_sv;
+ case verb::subscribe: return "SUBSCRIBE"_sv;
+ case verb::unsubscribe: return "UNSUBSCRIBE"_sv;
+
+ case verb::patch: return "PATCH"_sv;
+ case verb::purge: return "PURGE"_sv;
+
+ case verb::mkcalendar: return "MKCALENDAR"_sv;
+
+ case verb::link: return "LINK"_sv;
+ case verb::unlink: return "UNLINK"_sv;
+
case verb::unknown:
- return "<unknown>";
+ return "<unknown>"_sv;
}
BOOST_THROW_EXCEPTION(std::invalid_argument{"unknown verb"});
@@ -108,34 +109,20 @@ string_to_verb(string_view v)
UNLOCK
UNSUBSCRIBE
*/
+ using namespace beast::detail::string_literals;
if(v.size() < 3)
return verb::unknown;
- // s must be null terminated
- auto const eq =
- [](string_view sv, char const* s)
- {
- auto p = sv.data();
- for(;;)
- {
- if(*s != *p)
- return false;
- ++s;
- ++p;
- if(! *s)
- return p == (sv.data() + sv.size());
- }
- };
auto c = v[0];
v.remove_prefix(1);
switch(c)
{
case 'A':
- if(v == "CL")
+ if(v == "CL"_sv)
return verb::acl;
break;
case 'B':
- if(v == "IND")
+ if(v == "IND"_sv)
return verb::bind;
break;
@@ -145,14 +132,14 @@ string_to_verb(string_view v)
switch(c)
{
case 'H':
- if(eq(v, "ECKOUT"))
+ if(v == "ECKOUT"_sv)
return verb::checkout;
break;
case 'O':
- if(eq(v, "NNECT"))
+ if(v == "NNECT"_sv)
return verb::connect;
- if(eq(v, "PY"))
+ if(v == "PY"_sv)
return verb::copy;
BOOST_FALLTHROUGH;
@@ -162,24 +149,24 @@ string_to_verb(string_view v)
break;
case 'D':
- if(eq(v, "ELETE"))
+ if(v == "ELETE"_sv)
return verb::delete_;
break;
case 'G':
- if(eq(v, "ET"))
+ if(v == "ET"_sv)
return verb::get;
break;
case 'H':
- if(eq(v, "EAD"))
+ if(v == "EAD"_sv)
return verb::head;
break;
case 'L':
- if(eq(v, "INK"))
+ if(v == "INK"_sv)
return verb::link;
- if(eq(v, "OCK"))
+ if(v == "OCK"_sv)
return verb::lock;
break;
@@ -189,31 +176,31 @@ string_to_verb(string_view v)
switch(c)
{
case '-':
- if(eq(v, "SEARCH"))
+ if(v == "SEARCH"_sv)
return verb::msearch;
break;
case 'E':
- if(eq(v, "RGE"))
+ if(v == "RGE"_sv)
return verb::merge;
break;
case 'K':
- if(eq(v, "ACTIVITY"))
+ if(v == "ACTIVITY"_sv)
return verb::mkactivity;
if(v[0] == 'C')
{
v.remove_prefix(1);
- if(eq(v, "ALENDAR"))
+ if(v == "ALENDAR"_sv)
return verb::mkcalendar;
- if(eq(v, "OL"))
+ if(v == "OL"_sv)
return verb::mkcol;
break;
}
break;
-
+
case 'O':
- if(eq(v, "VE"))
+ if(v == "VE"_sv)
return verb::move;
BOOST_FALLTHROUGH;
@@ -223,12 +210,12 @@ string_to_verb(string_view v)
break;
case 'N':
- if(eq(v, "OTIFY"))
+ if(v == "OTIFY"_sv)
return verb::notify;
break;
case 'O':
- if(eq(v, "PTIONS"))
+ if(v == "PTIONS"_sv)
return verb::options;
break;
@@ -238,26 +225,26 @@ string_to_verb(string_view v)
switch(c)
{
case 'A':
- if(eq(v, "TCH"))
+ if(v == "TCH"_sv)
return verb::patch;
break;
case 'O':
- if(eq(v, "ST"))
+ if(v == "ST"_sv)
return verb::post;
break;
case 'R':
- if(eq(v, "OPFIND"))
+ if(v == "OPFIND"_sv)
return verb::propfind;
- if(eq(v, "OPPATCH"))
+ if(v == "OPPATCH"_sv)
return verb::proppatch;
break;
case 'U':
- if(eq(v, "RGE"))
+ if(v == "RGE"_sv)
return verb::purge;
- if(eq(v, "T"))
+ if(v == "T"_sv)
return verb::put;
BOOST_FALLTHROUGH;
@@ -270,21 +257,21 @@ string_to_verb(string_view v)
if(v[0] != 'E')
break;
v.remove_prefix(1);
- if(eq(v, "BIND"))
+ if(v == "BIND"_sv)
return verb::rebind;
- if(eq(v, "PORT"))
+ if(v == "PORT"_sv)
return verb::report;
break;
case 'S':
- if(eq(v, "EARCH"))
+ if(v == "EARCH"_sv)
return verb::search;
- if(eq(v, "UBSCRIBE"))
+ if(v == "UBSCRIBE"_sv)
return verb::subscribe;
break;
case 'T':
- if(eq(v, "RACE"))
+ if(v == "RACE"_sv)
return verb::trace;
break;
@@ -292,13 +279,13 @@ string_to_verb(string_view v)
if(v[0] != 'N')
break;
v.remove_prefix(1);
- if(eq(v, "BIND"))
+ if(v == "BIND"_sv)
return verb::unbind;
- if(eq(v, "LINK"))
+ if(v == "LINK"_sv)
return verb::unlink;
- if(eq(v, "LOCK"))
+ if(v == "LOCK"_sv)
return verb::unlock;
- if(eq(v, "SUBSCRIBE"))
+ if(v == "SUBSCRIBE"_sv)
return verb::unsubscribe;
break;
diff --git a/boost/beast/http/impl/write.hpp b/boost/beast/http/impl/write.hpp
index 5636ce92f8..79b0c83d71 100644
--- a/boost/beast/http/impl/write.hpp
+++ b/boost/beast/http/impl/write.hpp
@@ -14,8 +14,9 @@
#include <boost/beast/core/async_base.hpp>
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/buffers_range.hpp>
-#include <boost/beast/core/ostream.hpp>
+#include <boost/beast/core/make_printable.hpp>
#include <boost/beast/core/stream_traits.hpp>
+#include <boost/beast/core/detail/is_invocable.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/write.hpp>
@@ -159,7 +160,7 @@ template<
class write_op
: public beast::async_base<
Handler, beast::executor_type<Stream>>
- , public net::coroutine
+ , public asio::coroutine
{
Stream& s_;
serializer<isRequest, Body, Fields>& sr_;
@@ -262,7 +263,7 @@ struct run_write_some_op
{
template<
class WriteHandler,
- class Stream,
+ class Stream,
bool isRequest, class Body, class Fields>
void
operator()(
@@ -903,7 +904,7 @@ operator<<(std::ostream& os,
{
typename Fields::writer fr{
h, h.version(), h.method()};
- return os << buffers(fr.get());
+ return os << beast::make_printable(fr.get());
}
template<class Fields>
@@ -913,7 +914,7 @@ operator<<(std::ostream& os,
{
typename Fields::writer fr{
h, h.version(), h.result_int()};
- return os << buffers(fr.get());
+ return os << beast::make_printable(fr.get());
}
template<bool isRequest, class Body, class Fields>
diff --git a/boost/beast/http/rfc7230.hpp b/boost/beast/http/rfc7230.hpp
index bc2498db52..c83494e666 100644
--- a/boost/beast/http/rfc7230.hpp
+++ b/boost/beast/http/rfc7230.hpp
@@ -190,17 +190,17 @@ public:
@return An iterator to the matching token, or `end()` if no
token exists.
*/
- template<class T>
+ BOOST_BEAST_DECL
const_iterator
- find(T const& s);
+ find(string_view const& s);
/** Return `true` if a token is present in the list.
@param s The token to find. A case-insensitive comparison is used.
*/
- template<class T>
+ BOOST_BEAST_DECL
bool
- exists(T const& s);
+ exists(string_view const& s);
};
//------------------------------------------------------------------------------
@@ -275,9 +275,9 @@ public:
@param s The token to find. A case-insensitive comparison is used.
*/
- template<class T>
+ BOOST_BEAST_DECL
bool
- exists(T const& s);
+ exists(string_view const& s);
};
/** A list of tokens in a comma separated HTTP field value.
diff --git a/boost/beast/http/string_body.hpp b/boost/beast/http/string_body.hpp
index 73a01a41fd..aeeefcc440 100644
--- a/boost/beast/http/string_body.hpp
+++ b/boost/beast/http/string_body.hpp
@@ -16,7 +16,6 @@
#include <boost/beast/http/message.hpp>
#include <boost/beast/core/buffers_range.hpp>
#include <boost/beast/core/detail/clamp.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/optional.hpp>
#include <cstdint>
diff --git a/boost/beast/http/vector_body.hpp b/boost/beast/http/vector_body.hpp
index b44ef0f625..c599e162b9 100644
--- a/boost/beast/http/vector_body.hpp
+++ b/boost/beast/http/vector_body.hpp
@@ -15,7 +15,6 @@
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/core/detail/clamp.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/optional.hpp>
#include <cstdint>
@@ -39,8 +38,7 @@ template<class T, class Allocator = std::allocator<T>>
struct vector_body
{
private:
- static_assert(sizeof(T) == 1 &&
- std::is_integral<T>::value,
+ static_assert(sizeof(T) == 1,
"T requirements not met");
public:
diff --git a/boost/beast/src.hpp b/boost/beast/src.hpp
index 87b4ab305f..2376c3fcc2 100644
--- a/boost/beast/src.hpp
+++ b/boost/beast/src.hpp
@@ -31,6 +31,7 @@ the program, with the macro BOOST_BEAST_SEPARATE_COMPILATION defined.
#include <boost/beast/core/detail/base64.ipp>
#include <boost/beast/core/detail/sha1.ipp>
+#include <boost/beast/core/detail/impl/temporary_buffer.ipp>
#include <boost/beast/core/impl/error.ipp>
#include <boost/beast/core/impl/file_posix.ipp>
#include <boost/beast/core/impl/file_stdio.ipp>
@@ -38,17 +39,20 @@ the program, with the macro BOOST_BEAST_SEPARATE_COMPILATION defined.
#include <boost/beast/core/impl/flat_static_buffer.ipp>
#include <boost/beast/core/impl/saved_handler.ipp>
#include <boost/beast/core/impl/static_buffer.ipp>
+#include <boost/beast/core/impl/string.ipp>
#include <boost/beast/http/detail/basic_parser.ipp>
#include <boost/beast/http/detail/rfc7230.ipp>
#include <boost/beast/http/impl/basic_parser.ipp>
#include <boost/beast/http/impl/error.ipp>
#include <boost/beast/http/impl/field.ipp>
+#include <boost/beast/http/impl/fields.ipp>
#include <boost/beast/http/impl/rfc7230.ipp>
#include <boost/beast/http/impl/status.ipp>
#include <boost/beast/http/impl/verb.ipp>
#include <boost/beast/websocket/detail/hybi13.ipp>
+#include <boost/beast/websocket/detail/mask.ipp>
#include <boost/beast/websocket/detail/pmd_extension.ipp>
#include <boost/beast/websocket/detail/prng.ipp>
#include <boost/beast/websocket/detail/service.ipp>
diff --git a/boost/beast/ssl/ssl_stream.hpp b/boost/beast/ssl/ssl_stream.hpp
index b96dbdda31..cab2463de2 100644
--- a/boost/beast/ssl/ssl_stream.hpp
+++ b/boost/beast/ssl/ssl_stream.hpp
@@ -655,12 +655,7 @@ public:
teardown(
boost::beast::role_type role,
ssl_stream<SyncStream>& stream,
- boost::system::error_code& ec)
- {
- // Just forward it to the underlying ssl::stream
- using boost::beast::websocket::teardown;
- teardown(role, *stream.p_, ec);
- }
+ boost::system::error_code& ec);
template<class AsyncStream, class TeardownHandler>
friend
@@ -668,16 +663,37 @@ public:
async_teardown(
boost::beast::role_type role,
ssl_stream<AsyncStream>& stream,
- TeardownHandler&& handler)
- {
- // Just forward it to the underlying ssl::stream
- using boost::beast::websocket::async_teardown;
- async_teardown(role, *stream.p_,
- std::forward<TeardownHandler>(handler));
- }
+ TeardownHandler&& handler);
#endif
};
+#if ! BOOST_BEAST_DOXYGEN
+template<class SyncStream>
+void
+teardown(
+ boost::beast::role_type role,
+ ssl_stream<SyncStream>& stream,
+ boost::system::error_code& ec)
+{
+ // Just forward it to the underlying ssl::stream
+ using boost::beast::websocket::teardown;
+ teardown(role, *stream.p_, ec);
+}
+
+template<class AsyncStream, class TeardownHandler>
+void
+async_teardown(
+ boost::beast::role_type role,
+ ssl_stream<AsyncStream>& stream,
+ TeardownHandler&& handler)
+{
+ // Just forward it to the underlying ssl::stream
+ using boost::beast::websocket::async_teardown;
+ async_teardown(role, *stream.p_,
+ std::forward<TeardownHandler>(handler));
+}
+#endif
+
} // beast
} // boost
diff --git a/boost/beast/version.hpp b/boost/beast/version.hpp
index b689881bce..02144712eb 100644
--- a/boost/beast/version.hpp
+++ b/boost/beast/version.hpp
@@ -20,7 +20,7 @@
This is a simple integer that is incremented by one every
time a set of code changes is merged to the develop branch.
*/
-#define BOOST_BEAST_VERSION 248
+#define BOOST_BEAST_VERSION 266
#define BOOST_BEAST_VERSION_STRING "Boost.Beast/" BOOST_STRINGIZE(BOOST_BEAST_VERSION)
diff --git a/boost/beast/websocket/detail/decorator.hpp b/boost/beast/websocket/detail/decorator.hpp
index cab7f9a298..03c1c8f637 100644
--- a/boost/beast/websocket/detail/decorator.hpp
+++ b/boost/beast/websocket/detail/decorator.hpp
@@ -11,7 +11,6 @@
#define BOOST_BEAST_WEBSOCKET_DETAIL_DECORATOR_HPP
#include <boost/beast/websocket/rfc6455.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/core/exchange.hpp>
#include <boost/type_traits/make_void.hpp>
#include <algorithm>
@@ -213,7 +212,7 @@ struct decorator::vtable_impl<F, true>
void
move(storage& dst, storage& src) noexcept
{
- auto& f = *reinterpret_cast<F*>(&src.buf_);
+ auto& f = *beast::detail::launder_cast<F*>(&src.buf_);
::new (&dst.buf_) F(std::move(f));
}
@@ -221,7 +220,7 @@ struct decorator::vtable_impl<F, true>
void
destroy(storage& dst) noexcept
{
- reinterpret_cast<F*>(&dst.buf_)->~F();
+ beast::detail::launder_cast<F*>(&dst.buf_)->~F();
}
static
@@ -229,7 +228,7 @@ struct decorator::vtable_impl<F, true>
invoke_req(storage& dst, request_type& req)
{
maybe_invoke<F, request_type>{}(
- *reinterpret_cast<F*>(&dst.buf_), req);
+ *beast::detail::launder_cast<F*>(&dst.buf_), req);
}
static
@@ -237,7 +236,7 @@ struct decorator::vtable_impl<F, true>
invoke_res(storage& dst, response_type& res)
{
maybe_invoke<F, response_type>{}(
- *reinterpret_cast<F*>(&dst.buf_), res);
+ *beast::detail::launder_cast<F*>(&dst.buf_), res);
}
static
diff --git a/boost/beast/websocket/detail/frame.hpp b/boost/beast/websocket/detail/frame.hpp
index 1603bb556e..f217e04a52 100644
--- a/boost/beast/websocket/detail/frame.hpp
+++ b/boost/beast/websocket/detail/frame.hpp
@@ -14,20 +14,10 @@
#include <boost/beast/websocket/error.hpp>
#include <boost/beast/websocket/rfc6455.hpp>
#include <boost/beast/websocket/detail/utf8_checker.hpp>
-#include <boost/beast/core/buffers_suffix.hpp>
#include <boost/beast/core/flat_static_buffer.hpp>
-#include <boost/beast/core/static_string.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/assert.hpp>
-// This is for <boost/endian/buffers.hpp>
-#if BOOST_WORKAROUND(BOOST_MSVC, > 0)
-# pragma warning (push)
-# pragma warning (disable: 4127) // conditional expression is constant
-#endif
-#include <boost/endian/buffers.hpp>
-#if BOOST_WORKAROUND(BOOST_MSVC, > 0)
-# pragma warning (pop)
-#endif
+#include <boost/endian/conversion.hpp>
#include <cstdint>
namespace boost {
@@ -35,56 +25,6 @@ namespace beast {
namespace websocket {
namespace detail {
-inline
-std::uint16_t
-big_uint16_to_native(void const* buf)
-{
- auto const p = static_cast<
- std::uint8_t const*>(buf);
- return (p[0]<<8) + p[1];
-}
-
-inline
-std::uint64_t
-big_uint64_to_native(void const* buf)
-{
- auto const p = static_cast<
- std::uint8_t const*>(buf);
- return
- (static_cast<std::uint64_t>(p[0])<<56) +
- (static_cast<std::uint64_t>(p[1])<<48) +
- (static_cast<std::uint64_t>(p[2])<<40) +
- (static_cast<std::uint64_t>(p[3])<<32) +
- (static_cast<std::uint64_t>(p[4])<<24) +
- (static_cast<std::uint64_t>(p[5])<<16) +
- (static_cast<std::uint64_t>(p[6])<< 8) +
- p[7];
-}
-
-inline
-std::uint32_t
-little_uint32_to_native(void const* buf)
-{
- auto const p = static_cast<
- std::uint8_t const*>(buf);
- return
- p[0] +
- (static_cast<std::uint32_t>(p[1])<< 8) +
- (static_cast<std::uint32_t>(p[2])<<16) +
- (static_cast<std::uint32_t>(p[3])<<24);
-}
-
-inline
-void
-native_to_little_uint32(std::uint32_t v, void* buf)
-{
- auto p = static_cast<std::uint8_t*>(buf);
- p[0] = v & 0xff;
- p[1] = (v >> 8) & 0xff;
- p[2] = (v >> 16) & 0xff;
- p[3] = (v >> 24) & 0xff;
-}
-
// frame header opcodes
enum class opcode : std::uint8_t
{
@@ -193,7 +133,6 @@ template<class DynamicBuffer>
void
write(DynamicBuffer& db, frame_header const& fh)
{
- using namespace boost::endian;
std::size_t n;
std::uint8_t b[14];
b[0] = (fh.fin ? 0x80 : 0x00) | static_cast<std::uint8_t>(fh.op);
@@ -212,19 +151,24 @@ write(DynamicBuffer& db, frame_header const& fh)
else if(fh.len <= 65535)
{
b[1] |= 126;
- ::new(&b[2]) big_uint16_buf_t{
- (std::uint16_t)fh.len};
+ auto len_be = endian::native_to_big(
+ static_cast<std::uint16_t>(fh.len));
+ std::memcpy(&b[2], &len_be, sizeof(len_be));
n = 4;
}
else
{
b[1] |= 127;
- ::new(&b[2]) big_uint64_buf_t{fh.len};
+ auto len_be = endian::native_to_big(
+ static_cast<std::uint64_t>(fh.len));
+ std::memcpy(&b[2], &len_be, sizeof(len_be));
n = 10;
}
if(fh.mask)
{
- native_to_little_uint32(fh.key, &b[n]);
+ auto key_le = endian::native_to_little(
+ static_cast<std::uint32_t>(fh.key));
+ std::memcpy(&b[n], &key_le, sizeof(key_le));
n += 4;
}
db.commit(net::buffer_copy(
@@ -254,8 +198,7 @@ read_close(
Buffers const& bs,
error_code& ec)
{
- using namespace boost::endian;
- auto n = buffer_bytes(bs);
+ auto const n = buffer_bytes(bs);
BOOST_ASSERT(n <= 125);
if(n == 0)
{
@@ -269,36 +212,29 @@ read_close(
ec = error::bad_close_size;
return;
}
- buffers_suffix<Buffers> cb(bs);
- {
- std::uint8_t b[2];
- net::buffer_copy(net::buffer(b), cb);
- cr.code = big_uint16_to_native(&b[0]);
- cb.consume(2);
- n -= 2;
- if(! is_valid_close_code(cr.code))
- {
- // invalid close code
- ec = error::bad_close_code;
- return;
- }
- }
- if(n > 0)
+
+ std::uint16_t code_be;
+ cr.reason.resize(n - 2);
+ std::array<net::mutable_buffer, 2> out_bufs{{
+ net::mutable_buffer(&code_be, sizeof(code_be)),
+ net::mutable_buffer(&cr.reason[0], n - 2)}};
+
+ net::buffer_copy(out_bufs, bs);
+
+ cr.code = endian::big_to_native(code_be);
+ if(! is_valid_close_code(cr.code))
{
- cr.reason.resize(n);
- net::buffer_copy(
- net::buffer(&cr.reason[0], n), cb);
- if(! check_utf8(
- cr.reason.data(), cr.reason.size()))
- {
- // not valid utf-8
- ec = error::bad_close_payload;
- return;
- }
+ // invalid close code
+ ec = error::bad_close_code;
+ return;
}
- else
+
+ if(n > 2 && !check_utf8(
+ cr.reason.data(), cr.reason.size()))
{
- cr.reason = "";
+ // not valid utf-8
+ ec = error::bad_close_payload;
+ return;
}
ec = {};
}
diff --git a/boost/beast/websocket/detail/hybi13.ipp b/boost/beast/websocket/detail/hybi13.ipp
index b0ed57756b..0cbab15372 100644
--- a/boost/beast/websocket/detail/hybi13.ipp
+++ b/boost/beast/websocket/detail/hybi13.ipp
@@ -27,18 +27,12 @@ void
make_sec_ws_key(sec_ws_key_type& key)
{
auto g = make_prng(true);
- char a[16];
- for(int i = 0; i < 16; i += 4)
- {
- auto const v = g();
- a[i ] = v & 0xff;
- a[i+1] = (v >> 8) & 0xff;
- a[i+2] = (v >> 16) & 0xff;
- a[i+3] = (v >> 24) & 0xff;
- }
+ std::uint32_t a[4];
+ for (auto& v : a)
+ v = g();
key.resize(key.max_size());
key.resize(beast::detail::base64::encode(
- key.data(), &a[0], 16));
+ key.data(), &a[0], sizeof(a)));
}
void
@@ -47,11 +41,12 @@ make_sec_ws_accept(
string_view key)
{
BOOST_ASSERT(key.size() <= sec_ws_key_type::max_size_n);
- static_string<sec_ws_key_type::max_size_n + 36> m(key);
- m.append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
+ using namespace beast::detail::string_literals;
+ auto const guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"_sv;
beast::detail::sha1_context ctx;
beast::detail::init(ctx);
- beast::detail::update(ctx, m.data(), m.size());
+ beast::detail::update(ctx, key.data(), key.size());
+ beast::detail::update(ctx, guid.data(), guid.size());
char digest[beast::detail::sha1_context::digest_size];
beast::detail::finish(ctx, &digest[0]);
accept.resize(accept.max_size());
diff --git a/boost/beast/websocket/detail/mask.hpp b/boost/beast/websocket/detail/mask.hpp
index ade89fdae5..58797372e5 100644
--- a/boost/beast/websocket/detail/mask.hpp
+++ b/boost/beast/websocket/detail/mask.hpp
@@ -26,62 +26,27 @@ namespace detail {
using prepared_key = std::array<unsigned char, 4>;
-inline
+BOOST_BEAST_DECL
void
-prepare_key(prepared_key& prepared, std::uint32_t key)
-{
- prepared[0] = (key >> 0) & 0xff;
- prepared[1] = (key >> 8) & 0xff;
- prepared[2] = (key >> 16) & 0xff;
- prepared[3] = (key >> 24) & 0xff;
-}
-
-template<std::size_t N>
-void
-rol(std::array<unsigned char, N>& v, std::size_t n)
-{
- auto v0 = v;
- for(std::size_t i = 0; i < v.size(); ++i )
- v[i] = v0[(i + n) % v.size()];
-}
+prepare_key(prepared_key& prepared, std::uint32_t key);
// Apply mask in place
//
-inline
+BOOST_BEAST_DECL
void
-mask_inplace(net::mutable_buffer& b, prepared_key& key)
-{
- auto n = b.size();
- auto mask = key; // avoid aliasing
- auto p = static_cast<unsigned char*>(b.data());
- while(n >= 4)
- {
- for(int i = 0; i < 4; ++i)
- p[i] ^= mask[i];
- p += 4;
- n -= 4;
- }
- if(n > 0)
- {
- for(std::size_t i = 0; i < n; ++i)
- p[i] ^= mask[i];
- rol(key, n);
- }
-}
+mask_inplace(net::mutable_buffer const& b, prepared_key& key);
// Apply mask in place
//
-template<
- class MutableBufferSequence,
- class KeyType>
+template<class MutableBufferSequence>
void
mask_inplace(
MutableBufferSequence const& buffers,
- KeyType& key)
+ prepared_key& key)
{
for(net::mutable_buffer b :
beast::buffers_range_ref(buffers))
- mask_inplace(b, key);
+ detail::mask_inplace(b, key);
}
} // detail
@@ -89,4 +54,10 @@ mask_inplace(
} // beast
} // boost
+
+#if BOOST_BEAST_HEADER_ONLY
+#include <boost/beast/websocket/detail/mask.ipp>
+#endif
+
+
#endif
diff --git a/boost/beast/websocket/detail/mask.ipp b/boost/beast/websocket/detail/mask.ipp
new file mode 100644
index 0000000000..6c36d56bc1
--- /dev/null
+++ b/boost/beast/websocket/detail/mask.ipp
@@ -0,0 +1,66 @@
+//
+// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_WEBSOCKET_DETAIL_MASK_IPP
+#define BOOST_BEAST_WEBSOCKET_DETAIL_MASK_IPP
+
+#include <boost/beast/websocket/detail/mask.hpp>
+
+namespace boost {
+namespace beast {
+namespace websocket {
+namespace detail {
+
+void
+prepare_key(prepared_key& prepared, std::uint32_t key)
+{
+ prepared[0] = (key >> 0) & 0xff;
+ prepared[1] = (key >> 8) & 0xff;
+ prepared[2] = (key >> 16) & 0xff;
+ prepared[3] = (key >> 24) & 0xff;
+}
+
+inline
+void
+rol(prepared_key& v, std::size_t n)
+{
+ auto v0 = v;
+ for(std::size_t i = 0; i < v.size(); ++i )
+ v[i] = v0[(i + n) % v.size()];
+}
+
+// Apply mask in place
+//
+void
+mask_inplace(net::mutable_buffer const& b, prepared_key& key)
+{
+ auto n = b.size();
+ auto const mask = key; // avoid aliasing
+ auto p = static_cast<unsigned char*>(b.data());
+ while(n >= 4)
+ {
+ for(int i = 0; i < 4; ++i)
+ p[i] ^= mask[i];
+ p += 4;
+ n -= 4;
+ }
+ if(n > 0)
+ {
+ for(std::size_t i = 0; i < n; ++i)
+ p[i] ^= mask[i];
+ rol(key, n);
+ }
+}
+
+} // detail
+} // websocket
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/websocket/detail/pmd_extension.ipp b/boost/beast/websocket/detail/pmd_extension.ipp
index 790998e8ff..005feec19d 100644
--- a/boost/beast/websocket/detail/pmd_extension.ipp
+++ b/boost/beast/websocket/detail/pmd_extension.ipp
@@ -52,11 +52,11 @@ pmd_read_impl(pmd_offer& offer, http::ext_list const& list)
for(auto const& ext : list)
{
- if(iequals(ext.first, "permessage-deflate"))
+ if(beast::iequals(ext.first, "permessage-deflate"))
{
for(auto const& param : ext.second)
{
- if(iequals(param.first,
+ if(beast::iequals(param.first,
"server_max_window_bits"))
{
if(offer.server_max_window_bits != 0)
@@ -84,7 +84,7 @@ pmd_read_impl(pmd_offer& offer, http::ext_list const& list)
return; // MUST decline
}
}
- else if(iequals(param.first,
+ else if(beast::iequals(param.first,
"client_max_window_bits"))
{
if(offer.client_max_window_bits != 0)
@@ -112,7 +112,7 @@ pmd_read_impl(pmd_offer& offer, http::ext_list const& list)
offer.client_max_window_bits = -1;
}
}
- else if(iequals(param.first,
+ else if(beast::iequals(param.first,
"server_no_context_takeover"))
{
if(offer.server_no_context_takeover)
@@ -131,7 +131,7 @@ pmd_read_impl(pmd_offer& offer, http::ext_list const& list)
}
offer.server_no_context_takeover = true;
}
- else if(iequals(param.first,
+ else if(beast::iequals(param.first,
"client_no_context_takeover"))
{
if(offer.client_no_context_takeover)
diff --git a/boost/beast/websocket/detail/prng.hpp b/boost/beast/websocket/detail/prng.hpp
index 35409b5837..6eb474f2f0 100644
--- a/boost/beast/websocket/detail/prng.hpp
+++ b/boost/beast/websocket/detail/prng.hpp
@@ -11,8 +11,8 @@
#define BOOST_BEAST_WEBSOCKET_DETAIL_PRNG_HPP
#include <boost/beast/core/detail/config.hpp>
+#include <boost/config.hpp>
#include <cstdint>
-#include <limits>
#include <random>
namespace boost {
@@ -20,66 +20,7 @@ namespace beast {
namespace websocket {
namespace detail {
-// Type-erased UniformRandomBitGenerator
-// with 32-bit unsigned integer value_type
-//
-class prng
-{
-protected:
- virtual ~prng() = default;
- virtual prng& acquire() noexcept = 0;
- virtual void release() noexcept = 0;
- virtual std::uint32_t operator()() noexcept = 0;
-
-public:
- using value_type = std::uint32_t;
-
- class ref
- {
- prng& p_;
-
- public:
- ref& operator=(ref const&) = delete;
-
- ~ref()
- {
- p_.release();
- }
-
- explicit
- ref(prng& p) noexcept
- : p_(p.acquire())
- {
- }
-
- ref(ref const& other) noexcept
- : p_(other.p_.acquire())
- {
- }
-
- value_type
- operator()() noexcept
- {
- return p_();
- }
-
- static
- value_type constexpr
- min() noexcept
- {
- return (std::numeric_limits<
- value_type>::min)();
- }
-
- static
- value_type constexpr
- max() noexcept
- {
- return (std::numeric_limits<
- value_type>::max)();
- }
- };
-};
+using generator = std::uint32_t(*)();
//------------------------------------------------------------------------------
@@ -90,25 +31,11 @@ BOOST_BEAST_DECL
std::uint32_t const*
prng_seed(std::seed_seq* ss = nullptr);
-// Acquire a PRNG using the no-TLS implementation
-//
-BOOST_BEAST_DECL
-prng::ref
-make_prng_no_tls(bool secure);
-
-// Acquire a PRNG using the TLS implementation
-//
-#ifndef BOOST_NO_CXX11_THREAD_LOCAL
-BOOST_BEAST_DECL
-prng::ref
-make_prng_tls(bool secure);
-#endif
-
// Acquire a PRNG using the TLS implementation if it
// is available, otherwise using the no-TLS implementation.
//
BOOST_BEAST_DECL
-prng::ref
+generator
make_prng(bool secure);
} // detail
diff --git a/boost/beast/websocket/detail/prng.ipp b/boost/beast/websocket/detail/prng.ipp
index 2807ca96e9..2d4e7f2771 100644
--- a/boost/beast/websocket/detail/prng.ipp
+++ b/boost/beast/websocket/detail/prng.ipp
@@ -13,14 +13,10 @@
#include <boost/beast/websocket/detail/prng.hpp>
#include <boost/beast/core/detail/chacha.hpp>
#include <boost/beast/core/detail/pcg.hpp>
-#include <boost/align/aligned_alloc.hpp>
-#include <boost/throw_exception.hpp>
#include <atomic>
#include <cstdlib>
#include <mutex>
-#include <new>
#include <random>
-#include <stdexcept>
namespace boost {
namespace beast {
@@ -59,264 +55,92 @@ prng_seed(std::seed_seq* ss)
//------------------------------------------------------------------------------
-template<class T>
-class prng_pool
+inline
+std::uint32_t
+make_nonce()
{
- std::mutex m_;
- T* head_ = nullptr;
-
-public:
- static
- prng_pool&
- instance()
- {
- static prng_pool p;
- return p;
- }
-
- ~prng_pool()
- {
- for(auto p = head_; p;)
- {
- auto next = p->next;
- p->~T();
- boost::alignment::aligned_free(p);
- p = next;
- }
- }
+ static std::atomic<std::uint32_t> nonce{0};
+ return ++nonce;
+}
- prng::ref
- acquire()
- {
- {
- std::lock_guard<
- std::mutex> g(m_);
- if(head_)
- {
- auto p = head_;
- head_ = head_->next;
- return prng::ref(*p);
- }
- }
- auto p = boost::alignment::aligned_alloc(
- 16, sizeof(T));
- if(! p)
- BOOST_THROW_EXCEPTION(std::bad_alloc{});
- return prng::ref(*(::new(p) T()));
- }
+inline
+beast::detail::pcg make_pcg()
+{
+ auto const pv = prng_seed();
+ return beast::detail::pcg{
+ ((static_cast<std::uint64_t>(pv[0])<<32)+pv[1]) ^
+ ((static_cast<std::uint64_t>(pv[2])<<32)+pv[3]) ^
+ ((static_cast<std::uint64_t>(pv[4])<<32)+pv[5]) ^
+ ((static_cast<std::uint64_t>(pv[6])<<32)+pv[7]), make_nonce()};
+}
- void
- release(T& t)
- {
- std::lock_guard<
- std::mutex> g(m_);
- t.next = head_;
- head_ = &t;
- }
-};
+#ifdef BOOST_NO_CXX11_THREAD_LOCAL
-prng::ref
-make_prng_no_tls(bool secure)
+inline
+std::uint32_t
+secure_generate()
{
- class fast_prng final : public prng
+ struct generator
{
- int refs_ = 0;
- beast::detail::pcg r_;
-
- public:
- fast_prng* next = nullptr;
-
- fast_prng()
- : r_(
- []{
- auto const pv = prng_seed();
- return
- ((static_cast<std::uint64_t>(pv[0])<<32)+pv[1]) ^
- ((static_cast<std::uint64_t>(pv[2])<<32)+pv[3]) ^
- ((static_cast<std::uint64_t>(pv[4])<<32)+pv[5]) ^
- ((static_cast<std::uint64_t>(pv[6])<<32)+pv[7]);
- }(),
- []{
- static std::atomic<
- std::uint32_t> nonce{0};
- return ++nonce;
- }())
- {
- }
-
- protected:
- prng&
- acquire() noexcept override
+ std::uint32_t operator()()
{
- ++refs_;
- return *this;
+ std::lock_guard<std::mutex> guard{mtx};
+ return gen();
}
- void
- release() noexcept override
- {
- if(--refs_ == 0)
- prng_pool<fast_prng>::instance().release(*this);
- }
-
- value_type
- operator()() noexcept override
- {
- return r_();
- }
+ beast::detail::chacha<20> gen;
+ std::mutex mtx;
};
-
- class secure_prng final : public prng
- {
- int refs_ = 0;
- beast::detail::chacha<20> r_;
-
- public:
- secure_prng* next = nullptr;
-
- secure_prng()
- : r_(prng_seed(), []
- {
- static std::atomic<
- std::uint64_t> nonce{0};
- return ++nonce;
- }())
- {
- }
-
- protected:
- prng&
- acquire() noexcept override
- {
- ++refs_;
- return *this;
- }
-
- void
- release() noexcept override
- {
- if(--refs_ == 0)
- prng_pool<secure_prng>::instance().release(*this);
- }
-
- value_type
- operator()() noexcept override
- {
- return r_();
- }
- };
-
- if(secure)
- return prng_pool<secure_prng>::instance().acquire();
-
- return prng_pool<fast_prng>::instance().acquire();
+ static generator gen{beast::detail::chacha<20>{prng_seed(), make_nonce()}};
+ return gen();
}
-//------------------------------------------------------------------------------
-
-#ifndef BOOST_NO_CXX11_THREAD_LOCAL
-
-prng::ref
-make_prng_tls(bool secure)
+inline
+std::uint32_t
+fast_generate()
{
- class fast_prng final : public prng
+ struct generator
{
- beast::detail::pcg r_;
-
- public:
- fast_prng()
- : r_(
- []{
- auto const pv = prng_seed();
- return
- ((static_cast<std::uint64_t>(pv[0])<<32)+pv[1]) ^
- ((static_cast<std::uint64_t>(pv[2])<<32)+pv[3]) ^
- ((static_cast<std::uint64_t>(pv[4])<<32)+pv[5]) ^
- ((static_cast<std::uint64_t>(pv[6])<<32)+pv[7]);
- }(),
- []{
- static std::atomic<
- std::uint32_t> nonce{0};
- return ++nonce;
- }())
- {
- }
-
- protected:
- prng&
- acquire() noexcept override
+ std::uint32_t operator()()
{
- return *this;
+ std::lock_guard<std::mutex> guard{mtx};
+ return gen();
}
- void
- release() noexcept override
- {
- }
-
- value_type
- operator()() noexcept override
- {
- return r_();
- }
+ beast::detail::pcg gen;
+ std::mutex mtx;
};
+ static generator gen{make_pcg()};
+ return gen();
+}
- class secure_prng final : public prng
- {
- beast::detail::chacha<20> r_;
-
- public:
- secure_prng()
- : r_(prng_seed(), []
- {
- static std::atomic<
- std::uint64_t> nonce{0};
- return ++nonce;
- }())
- {
- }
-
- protected:
- prng&
- acquire() noexcept override
- {
- return *this;
- }
-
- void
- release() noexcept override
- {
- }
-
- value_type
- operator()() noexcept override
- {
- return r_();
- }
- };
+#else
- if(secure)
- {
- thread_local secure_prng sp;
- return prng::ref(sp);
- }
+inline
+std::uint32_t
+secure_generate()
+{
+ thread_local static beast::detail::chacha<20> gen{prng_seed(), make_nonce()};
+ return gen();
+}
- thread_local fast_prng fp;
- return prng::ref(fp);
+inline
+std::uint32_t
+fast_generate()
+{
+ thread_local static beast::detail::pcg gen{make_pcg()};
+ return gen();
}
#endif
-//------------------------------------------------------------------------------
-
-prng::ref
+generator
make_prng(bool secure)
{
-#ifdef BOOST_NO_CXX11_THREAD_LOCAL
- return make_prng_no_tls(secure);
-#else
- return make_prng_tls(secure);
-#endif
+ if (secure)
+ return &secure_generate;
+ else
+ return &fast_generate;
}
} // detail
diff --git a/boost/beast/websocket/impl/accept.hpp b/boost/beast/websocket/impl/accept.hpp
index 4b989b56c7..1e33d8b40a 100644
--- a/boost/beast/websocket/impl/accept.hpp
+++ b/boost/beast/websocket/impl/accept.hpp
@@ -21,7 +21,6 @@
#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/core/stream_traits.hpp>
#include <boost/beast/core/detail/buffer.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/post.hpp>
@@ -80,13 +79,8 @@ build_response(
decorator_opt(res);
decorator(res);
if(! res.count(http::field::server))
- {
- // VFALCO this is weird..
- BOOST_STATIC_ASSERT(sizeof(
- BOOST_BEAST_VERSION_STRING) < 20);
- static_string<20> s(BOOST_BEAST_VERSION_STRING);
- res.set(http::field::server, s);
- }
+ res.set(http::field::server,
+ string_view(BOOST_BEAST_VERSION_STRING));
};
auto err =
[&](error e)
@@ -172,7 +166,7 @@ template<class Handler>
class stream<NextLayer, deflateSupported>::response_op
: public beast::stable_async_base<
Handler, beast::executor_type<stream>>
- , public net::coroutine
+ , public asio::coroutine
{
boost::weak_ptr<impl_type> wp_;
error_code result_; // must come before res_
@@ -247,7 +241,7 @@ template<class Handler, class Decorator>
class stream<NextLayer, deflateSupported>::accept_op
: public beast::stable_async_base<
Handler, beast::executor_type<stream>>
- , public net::coroutine
+ , public asio::coroutine
{
boost::weak_ptr<impl_type> wp_;
http::request_parser<http::empty_body>& p_;
diff --git a/boost/beast/websocket/impl/close.hpp b/boost/beast/websocket/impl/close.hpp
index 03078d9232..d59374ccd3 100644
--- a/boost/beast/websocket/impl/close.hpp
+++ b/boost/beast/websocket/impl/close.hpp
@@ -38,7 +38,7 @@ template<class Handler>
class stream<NextLayer, deflateSupported>::close_op
: public beast::stable_async_base<
Handler, beast::executor_type<stream>>
- , public net::coroutine
+ , public asio::coroutine
{
boost::weak_ptr<impl_type> wp_;
error_code ev_;
diff --git a/boost/beast/websocket/impl/handshake.hpp b/boost/beast/websocket/impl/handshake.hpp
index 21fba99738..645b1a3a30 100644
--- a/boost/beast/websocket/impl/handshake.hpp
+++ b/boost/beast/websocket/impl/handshake.hpp
@@ -37,7 +37,7 @@ template<class Handler>
class stream<NextLayer, deflateSupported>::handshake_op
: public beast::stable_async_base<Handler,
beast::executor_type<stream>>
- , public net::coroutine
+ , public asio::coroutine
{
struct data
{
diff --git a/boost/beast/websocket/impl/ping.hpp b/boost/beast/websocket/impl/ping.hpp
index 350505c081..6f92d7c725 100644
--- a/boost/beast/websocket/impl/ping.hpp
+++ b/boost/beast/websocket/impl/ping.hpp
@@ -35,7 +35,7 @@ template<class Handler>
class stream<NextLayer, deflateSupported>::ping_op
: public beast::stable_async_base<
Handler, beast::executor_type<stream>>
- , public net::coroutine
+ , public asio::coroutine
{
boost::weak_ptr<impl_type> wp_;
detail::frame_buffer& fb_;
@@ -115,7 +115,7 @@ public:
template<class NextLayer, bool deflateSupported>
template<class Executor>
class stream<NextLayer, deflateSupported>::idle_ping_op
- : public net::coroutine
+ : public asio::coroutine
, public boost::empty_value<Executor>
{
boost::weak_ptr<impl_type> wp_;
@@ -176,7 +176,8 @@ public:
impl.op_idle_ping.emplace(std::move(*this));
impl.wr_block.lock(this);
BOOST_ASIO_CORO_YIELD
- net::post(this->get(), std::move(*this));
+ net::post(
+ this->get_executor(), std::move(*this));
BOOST_ASSERT(impl.wr_block.is_locked(this));
}
if(impl.check_stop_now(ec))
diff --git a/boost/beast/websocket/impl/read.hpp b/boost/beast/websocket/impl/read.hpp
index 8be18e5975..86c8940fc7 100644
--- a/boost/beast/websocket/impl/read.hpp
+++ b/boost/beast/websocket/impl/read.hpp
@@ -48,7 +48,7 @@ template<class Handler, class MutableBufferSequence>
class stream<NextLayer, deflateSupported>::read_some_op
: public beast::async_base<
Handler, beast::executor_type<stream>>
- , public net::coroutine
+ , public asio::coroutine
{
boost::weak_ptr<impl_type> wp_;
MutableBufferSequence bs_;
@@ -619,7 +619,7 @@ template<class Handler, class DynamicBuffer>
class stream<NextLayer, deflateSupported>::read_op
: public beast::async_base<
Handler, beast::executor_type<stream>>
- , public net::coroutine
+ , public asio::coroutine
{
boost::weak_ptr<impl_type> wp_;
DynamicBuffer& b_;
@@ -664,21 +664,22 @@ public:
auto& impl = *sp;
using mutable_buffers_type = typename
DynamicBuffer::mutable_buffers_type;
- boost::optional<mutable_buffers_type> mb;
BOOST_ASIO_CORO_REENTER(*this)
{
do
{
- mb = beast::detail::dynamic_buffer_prepare(b_,
- clamp(impl.read_size_hint_db(b_), limit_),
- ec, error::buffer_overflow);
- if(impl.check_stop_now(ec))
- goto upcall;
-
// VFALCO TODO use boost::beast::bind_continuation
BOOST_ASIO_CORO_YIELD
- read_some_op<read_op, mutable_buffers_type>(
- std::move(*this), sp, *mb);
+ {
+ auto mb = beast::detail::dynamic_buffer_prepare(b_,
+ clamp(impl.read_size_hint_db(b_), limit_),
+ ec, error::buffer_overflow);
+ if(impl.check_stop_now(ec))
+ goto upcall;
+ read_some_op<read_op, mutable_buffers_type>(
+ std::move(*this), sp, *mb);
+ }
+
b_.commit(bytes_transferred);
bytes_written_ += bytes_transferred;
if(ec)
diff --git a/boost/beast/websocket/impl/stream.hpp b/boost/beast/websocket/impl/stream.hpp
index 150748c453..539e255192 100644
--- a/boost/beast/websocket/impl/stream.hpp
+++ b/boost/beast/websocket/impl/stream.hpp
@@ -25,11 +25,8 @@
#include <boost/beast/core/buffers_suffix.hpp>
#include <boost/beast/core/flat_static_buffer.hpp>
#include <boost/beast/core/detail/clamp.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
-#include <boost/asio/bind_executor.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/assert.hpp>
-#include <boost/endian/buffers.hpp>
#include <boost/make_shared.hpp>
#include <boost/throw_exception.hpp>
#include <algorithm>
@@ -64,7 +61,7 @@ stream(Args&&... args)
template<class NextLayer, bool deflateSupported>
auto
stream<NextLayer, deflateSupported>::
-get_executor() const noexcept ->
+get_executor() noexcept ->
executor_type
{
return impl_->stream().get_executor();
@@ -140,12 +137,7 @@ read_size_hint(DynamicBuffer& buffer) const
static_assert(
net::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer type requirements not met");
- auto const initial_size = (std::min)(
- +tcp_frame_size,
- buffer.max_size() - buffer.size());
- if(initial_size == 0)
- return 1; // buffer is full
- return read_size_hint(initial_size);
+ return impl_->read_size_hint_db(buffer);
}
//------------------------------------------------------------------------------
diff --git a/boost/beast/websocket/impl/stream_impl.hpp b/boost/beast/websocket/impl/stream_impl.hpp
index ec5557c361..5bcd9c78ab 100644
--- a/boost/beast/websocket/impl/stream_impl.hpp
+++ b/boost/beast/websocket/impl/stream_impl.hpp
@@ -30,9 +30,7 @@
#include <boost/beast/core/static_buffer.hpp>
#include <boost/beast/core/stream_traits.hpp>
#include <boost/beast/core/detail/clamp.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/beast/version.hpp>
-#include <boost/asio/bind_executor.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/core/empty_value.hpp>
#include <boost/enable_shared_from_this.hpp>
@@ -99,7 +97,8 @@ struct stream<NextLayer, deflateSupported>::impl_type
bool wr_cont /* next write is a continuation */ = false;
bool wr_frag /* autofrag the current message */ = false;
bool wr_frag_opt /* autofrag option setting */ = true;
- bool wr_compress /* compress current message */ = false;
+ bool wr_compress; /* compress current message */
+ bool wr_compress_opt /* compress message setting */ = true;
detail::opcode wr_opcode /* message type */ = detail::opcode::text;
std::unique_ptr<
std::uint8_t[]> wr_buf; // write buffer
@@ -211,11 +210,14 @@ struct stream<NextLayer, deflateSupported>::impl_type
timer.cancel();
}
- // Called before each write frame
+ // Called just before sending
+ // the first frame of each message
void
begin_msg()
{
wr_frag = wr_frag_opt;
+ wr_compress =
+ this->pmd_enabled() && wr_compress_opt;
// Maintain the write buffer
if( this->pmd_enabled() ||
@@ -234,6 +236,8 @@ struct stream<NextLayer, deflateSupported>::impl_type
wr_buf_size = wr_buf_opt;
wr_buf.reset();
}
+
+ //
}
//--------------------------------------------------------------------------
@@ -275,13 +279,6 @@ struct stream<NextLayer, deflateSupported>::impl_type
return key;
}
- std::size_t
- read_size_hint(std::size_t initial_size) const
- {
- return this->read_size_hint_pmd(
- initial_size, rd_done, rd_remain, rd_fh);
- }
-
template<class DynamicBuffer>
std::size_t
read_size_hint_db(DynamicBuffer& buffer) const
@@ -291,7 +288,8 @@ struct stream<NextLayer, deflateSupported>::impl_type
buffer.max_size() - buffer.size());
if(initial_size == 0)
return 1; // buffer is full
- return this->read_size_hint(initial_size);
+ return this->read_size_hint_pmd(
+ initial_size, rd_done, rd_remain, rd_fh);
}
template<class DynamicBuffer>
@@ -771,10 +769,12 @@ parse_fh(
{
case 126:
{
- std::uint8_t tmp[2];
- BOOST_ASSERT(buffer_bytes(cb) >= sizeof(tmp));
- cb.consume(net::buffer_copy(net::buffer(tmp), cb));
- fh.len = detail::big_uint16_to_native(&tmp[0]);
+
+ std::uint16_t len_be;
+ BOOST_ASSERT(buffer_bytes(cb) >= sizeof(len_be));
+ cb.consume(net::buffer_copy(
+ net::mutable_buffer(&len_be, sizeof(len_be)), cb));
+ fh.len = endian::big_to_native(len_be);
if(fh.len < 126)
{
// length not canonical
@@ -785,10 +785,11 @@ parse_fh(
}
case 127:
{
- std::uint8_t tmp[8];
- BOOST_ASSERT(buffer_bytes(cb) >= sizeof(tmp));
- cb.consume(net::buffer_copy(net::buffer(tmp), cb));
- fh.len = detail::big_uint64_to_native(&tmp[0]);
+ std::uint64_t len_be;
+ BOOST_ASSERT(buffer_bytes(cb) >= sizeof(len_be));
+ cb.consume(net::buffer_copy(
+ net::mutable_buffer(&len_be, sizeof(len_be)), cb));
+ fh.len = endian::big_to_native(len_be);
if(fh.len < 65536)
{
// length not canonical
@@ -800,10 +801,11 @@ parse_fh(
}
if(fh.mask)
{
- std::uint8_t tmp[4];
- BOOST_ASSERT(buffer_bytes(cb) >= sizeof(tmp));
- cb.consume(net::buffer_copy(net::buffer(tmp), cb));
- fh.key = detail::little_uint32_to_native(&tmp[0]);
+ std::uint32_t key_le;
+ BOOST_ASSERT(buffer_bytes(cb) >= sizeof(key_le));
+ cb.consume(net::buffer_copy(
+ net::mutable_buffer(&key_le, sizeof(key_le)), cb));
+ fh.key = endian::little_to_native(key_le);
detail::prepare_key(rd_key, fh.key);
}
else
@@ -909,12 +911,10 @@ write_close(DynamicBuffer& db, close_reason const& cr)
if(fh.mask)
detail::prepare_key(key, fh.key);
{
- std::uint8_t tmp[2];
- ::new(&tmp[0]) big_uint16_buf_t{
- (std::uint16_t)cr.code};
+ auto code_be = endian::native_to_big<std::uint16_t>(cr.code);
auto mb = db.prepare(2);
net::buffer_copy(mb,
- net::buffer(tmp));
+ net::const_buffer(&code_be, sizeof(code_be)));
if(fh.mask)
detail::mask_inplace(mb, key);
db.commit(2);
diff --git a/boost/beast/websocket/impl/teardown.hpp b/boost/beast/websocket/impl/teardown.hpp
index 8e0913762c..2e2f0ad7e3 100644
--- a/boost/beast/websocket/impl/teardown.hpp
+++ b/boost/beast/websocket/impl/teardown.hpp
@@ -14,7 +14,7 @@
#include <boost/beast/core/bind_handler.hpp>
#include <boost/beast/core/stream_traits.hpp>
#include <boost/beast/core/detail/bind_continuation.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
+#include <boost/beast/core/detail/is_invocable.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/post.hpp>
#include <memory>
@@ -33,7 +33,7 @@ class teardown_tcp_op
Handler, beast::executor_type<
net::basic_stream_socket<
Protocol, Executor>>>
- , public net::coroutine
+ , public asio::coroutine
{
using socket_type =
net::basic_stream_socket<Protocol, Executor>;
diff --git a/boost/beast/websocket/impl/write.hpp b/boost/beast/websocket/impl/write.hpp
index 318693f512..2a82b677b3 100644
--- a/boost/beast/websocket/impl/write.hpp
+++ b/boost/beast/websocket/impl/write.hpp
@@ -41,7 +41,7 @@ template<class Handler, class Buffers>
class stream<NextLayer, deflateSupported>::write_some_op
: public beast::async_base<
Handler, beast::executor_type<stream>>
- , public net::coroutine
+ , public asio::coroutine
{
enum
{
diff --git a/boost/beast/websocket/option.hpp b/boost/beast/websocket/option.hpp
index 62ebfa4a2b..1133c4e1fa 100644
--- a/boost/beast/websocket/option.hpp
+++ b/boost/beast/websocket/option.hpp
@@ -11,15 +11,6 @@
#define BOOST_BEAST_WEBSOCKET_OPTION_HPP
#include <boost/beast/core/detail/config.hpp>
-#include <boost/beast/websocket/rfc6455.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
-#include <boost/throw_exception.hpp>
-#include <algorithm>
-#include <cstdint>
-#include <functional>
-#include <stdexcept>
-#include <type_traits>
-#include <utility>
namespace boost {
namespace beast {
diff --git a/boost/beast/websocket/stream.hpp b/boost/beast/websocket/stream.hpp
index a9d79d2de4..367a54537c 100644
--- a/boost/beast/websocket/stream.hpp
+++ b/boost/beast/websocket/stream.hpp
@@ -23,7 +23,6 @@
#include <boost/beast/core/role.hpp>
#include <boost/beast/core/stream_traits.hpp>
#include <boost/beast/core/string.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/beast/http/detail/type_traits.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/error.hpp>
@@ -220,7 +219,7 @@ public:
@return A copy of the executor that stream will use to dispatch handlers.
*/
executor_type
- get_executor() const noexcept;
+ get_executor() noexcept;
/** Get a reference to the next layer
diff --git a/boost/beast/zlib/detail/deflate_stream.hpp b/boost/beast/zlib/detail/deflate_stream.hpp
index 74ce6e5a9a..1460dd42dd 100644
--- a/boost/beast/zlib/detail/deflate_stream.hpp
+++ b/boost/beast/zlib/detail/deflate_stream.hpp
@@ -40,7 +40,6 @@
#include <boost/beast/zlib/error.hpp>
#include <boost/beast/zlib/zlib.hpp>
#include <boost/beast/zlib/detail/ranges.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/optional.hpp>
diff --git a/boost/beast/zlib/detail/deflate_stream.ipp b/boost/beast/zlib/detail/deflate_stream.ipp
index 4641697c36..5169843362 100644
--- a/boost/beast/zlib/detail/deflate_stream.ipp
+++ b/boost/beast/zlib/detail/deflate_stream.ipp
@@ -39,7 +39,6 @@
#include <boost/beast/zlib/detail/deflate_stream.hpp>
#include <boost/beast/zlib/detail/ranges.hpp>
-#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/make_unique.hpp>
@@ -623,6 +622,7 @@ init()
window_ = reinterpret_cast<Byte*>(buf_.get());
prev_ = reinterpret_cast<std::uint16_t*>(buf_.get() + nwindow);
+ std::memset(prev_, 0, nprev);
head_ = reinterpret_cast<std::uint16_t*>(buf_.get() + nwindow + nprev);
/* We overlay pending_buf_ and d_buf_ + l_buf_. This works
diff --git a/boost/bind/bind.hpp b/boost/bind/bind.hpp
index 4cedc5e9a4..711e0001e4 100644
--- a/boost/bind/bind.hpp
+++ b/boost/bind/bind.hpp
@@ -2136,7 +2136,7 @@ template<class F, class A1, class A2, class A3, class A4, class A5, class A6, cl
#undef BOOST_BIND_ST
#undef BOOST_BIND_NOEXCEPT
-#ifdef BOOST_BIND_ENABLE_STDCALL
+#if defined(BOOST_BIND_ENABLE_STDCALL) && !defined(_M_X64)
#define BOOST_BIND_CC __stdcall
#define BOOST_BIND_ST
@@ -2150,7 +2150,7 @@ template<class F, class A1, class A2, class A3, class A4, class A5, class A6, cl
#endif
-#ifdef BOOST_BIND_ENABLE_FASTCALL
+#if defined(BOOST_BIND_ENABLE_FASTCALL) && !defined(_M_X64)
#define BOOST_BIND_CC __fastcall
#define BOOST_BIND_ST
@@ -2197,7 +2197,7 @@ template<class F, class A1, class A2, class A3, class A4, class A5, class A6, cl
#undef BOOST_BIND_MF_CC
#undef BOOST_BIND_MF_NOEXCEPT
-#ifdef BOOST_MEM_FN_ENABLE_CDECL
+#if defined(BOOST_MEM_FN_ENABLE_CDECL) && !defined(_M_X64)
#define BOOST_BIND_MF_NAME(X) X##_cdecl
#define BOOST_BIND_MF_CC __cdecl
@@ -2212,7 +2212,7 @@ template<class F, class A1, class A2, class A3, class A4, class A5, class A6, cl
#endif
-#ifdef BOOST_MEM_FN_ENABLE_STDCALL
+#if defined(BOOST_MEM_FN_ENABLE_STDCALL) && !defined(_M_X64)
#define BOOST_BIND_MF_NAME(X) X##_stdcall
#define BOOST_BIND_MF_CC __stdcall
@@ -2227,7 +2227,7 @@ template<class F, class A1, class A2, class A3, class A4, class A5, class A6, cl
#endif
-#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
+#if defined(BOOST_MEM_FN_ENABLE_FASTCALL) && !defined(_M_X64)
#define BOOST_BIND_MF_NAME(X) X##_fastcall
#define BOOST_BIND_MF_CC __fastcall
diff --git a/boost/bind/mem_fn.hpp b/boost/bind/mem_fn.hpp
index 956e7d8885..fc83fd76ab 100644
--- a/boost/bind/mem_fn.hpp
+++ b/boost/bind/mem_fn.hpp
@@ -49,7 +49,7 @@ template<class V> struct mf
#undef BOOST_MEM_FN_CC
#undef BOOST_MEM_FN_NAME
-#ifdef BOOST_MEM_FN_ENABLE_CDECL
+#if defined(BOOST_MEM_FN_ENABLE_CDECL) && !defined(_M_X64)
#define BOOST_MEM_FN_NAME(X) inner_##X##_cdecl
#define BOOST_MEM_FN_CC __cdecl
@@ -61,7 +61,7 @@ template<class V> struct mf
#endif
-#ifdef BOOST_MEM_FN_ENABLE_STDCALL
+#if defined(BOOST_MEM_FN_ENABLE_STDCALL) && !defined(_M_X64)
#define BOOST_MEM_FN_NAME(X) inner_##X##_stdcall
#define BOOST_MEM_FN_CC __stdcall
@@ -73,7 +73,7 @@ template<class V> struct mf
#endif
-#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
+#if defined(BOOST_MEM_FN_ENABLE_FASTCALL) && !defined(_M_X64)
#define BOOST_MEM_FN_NAME(X) inner_##X##_fastcall
#define BOOST_MEM_FN_CC __fastcall
@@ -102,7 +102,7 @@ template<> struct mf<void>
#undef BOOST_MEM_FN_CC
#undef BOOST_MEM_FN_NAME
-#ifdef BOOST_MEM_FN_ENABLE_CDECL
+#if defined(BOOST_MEM_FN_ENABLE_CDECL) && !defined(_M_X64)
#define BOOST_MEM_FN_NAME(X) inner_##X##_cdecl
#define BOOST_MEM_FN_CC __cdecl
@@ -155,7 +155,7 @@ template<> struct mf<void>
#undef BOOST_MEM_FN_NAME2
#undef BOOST_MEM_FN_CC
-#ifdef BOOST_MEM_FN_ENABLE_CDECL
+#if defined(BOOST_MEM_FN_ENABLE_CDECL) && !defined(_M_X64)
#define BOOST_MEM_FN_NAME(X) X##_cdecl
#define BOOST_MEM_FN_NAME2(X) inner_##X##_cdecl
@@ -217,7 +217,7 @@ namespace _mfi
#undef BOOST_MEM_FN_CC
#undef BOOST_MEM_FN_NAME
-#ifdef BOOST_MEM_FN_ENABLE_CDECL
+#if defined(BOOST_MEM_FN_ENABLE_CDECL) && !defined(_M_X64)
#define BOOST_MEM_FN_NAME(X) X##_cdecl
#define BOOST_MEM_FN_CC __cdecl
@@ -229,7 +229,7 @@ namespace _mfi
#endif
-#ifdef BOOST_MEM_FN_ENABLE_STDCALL
+#if defined(BOOST_MEM_FN_ENABLE_STDCALL) && !defined(_M_X64)
#define BOOST_MEM_FN_NAME(X) X##_stdcall
#define BOOST_MEM_FN_CC __stdcall
@@ -241,7 +241,7 @@ namespace _mfi
#endif
-#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
+#if defined(BOOST_MEM_FN_ENABLE_FASTCALL) && !defined(_M_X64)
#define BOOST_MEM_FN_NAME(X) X##_fastcall
#define BOOST_MEM_FN_CC __fastcall
@@ -270,7 +270,7 @@ namespace _mfi
#undef BOOST_MEM_FN_NAME
#undef BOOST_MEM_FN_CC
-#ifdef BOOST_MEM_FN_ENABLE_CDECL
+#if defined(BOOST_MEM_FN_ENABLE_CDECL) && !defined(_M_X64)
#define BOOST_MEM_FN_NAME(X) X##_cdecl
#define BOOST_MEM_FN_CC __cdecl
@@ -282,7 +282,7 @@ namespace _mfi
#endif
-#ifdef BOOST_MEM_FN_ENABLE_STDCALL
+#if defined(BOOST_MEM_FN_ENABLE_STDCALL) && !defined(_M_X64)
#define BOOST_MEM_FN_NAME(X) X##_stdcall
#define BOOST_MEM_FN_CC __stdcall
@@ -294,7 +294,7 @@ namespace _mfi
#endif
-#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
+#if defined(BOOST_MEM_FN_ENABLE_FASTCALL) && !defined(_M_X64)
#define BOOST_MEM_FN_NAME(X) X##_fastcall
#define BOOST_MEM_FN_CC __fastcall
diff --git a/boost/circular_buffer.hpp b/boost/circular_buffer.hpp
index f0530805ec..90d920ba91 100644
--- a/boost/circular_buffer.hpp
+++ b/boost/circular_buffer.hpp
@@ -8,6 +8,10 @@
// See www.boost.org/libs/circular_buffer for documentation.
+/*! @file
+Includes <boost/circular_buffer/base.hpp>
+*/
+
#if !defined(BOOST_CIRCULAR_BUFFER_HPP)
#define BOOST_CIRCULAR_BUFFER_HPP
@@ -19,12 +23,12 @@
#include <boost/config/workaround.hpp>
#include <boost/static_assert.hpp>
-// BOOST_CB_ENABLE_DEBUG: Debug support control.
+/*! Debug support control. */
#if !defined(BOOST_CB_ENABLE_DEBUG)
#define BOOST_CB_ENABLE_DEBUG 0
#endif
-// BOOST_CB_ASSERT: Runtime assertion.
+/*! INTERNAL ONLY */
#if BOOST_CB_ENABLE_DEBUG
#include <boost/assert.hpp>
#define BOOST_CB_ASSERT(Expr) BOOST_ASSERT(Expr)
@@ -32,7 +36,7 @@
#define BOOST_CB_ASSERT(Expr) ((void)0)
#endif
-// BOOST_CB_IS_CONVERTIBLE: Check if Iterator::value_type is convertible to Type.
+/*! INTERNAL ONLY */
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0550) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
#define BOOST_CB_IS_CONVERTIBLE(Iterator, Type) ((void)0)
#else
@@ -42,8 +46,7 @@
BOOST_STATIC_ASSERT((is_convertible<typename std::iterator_traits<Iterator>::value_type, Type>::value))
#endif
-// BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS:
-// Check if the STL provides templated iterator constructors for its containers.
+/*! INTERNAL ONLY */
#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
#define BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS BOOST_STATIC_ASSERT(false);
#else
diff --git a/boost/circular_buffer/base.hpp b/boost/circular_buffer/base.hpp
index aae90f5939..ac96096047 100644
--- a/boost/circular_buffer/base.hpp
+++ b/boost/circular_buffer/base.hpp
@@ -49,14 +49,14 @@ namespace boost {
\brief Circular buffer - a STL compliant container.
\tparam T The type of the elements stored in the <code>circular_buffer</code>.
\par Type Requirements T
- The <code>T</code> has to be <a href="http://www.sgi.com/tech/stl/Assignable.html">
+ The <code>T</code> has to be <a href="https://www.boost.org/sgi/stl/Assignable.html">
SGIAssignable</a> (SGI STL defined combination of <a href="../../../utility/Assignable.html">
Assignable</a> and <a href="../../../utility/CopyConstructible.html">CopyConstructible</a>).
- Moreover <code>T</code> has to be <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">
+ Moreover <code>T</code> has to be <a href="https://www.boost.org/sgi/stl/DefaultConstructible.html">
DefaultConstructible</a> if supplied as a default parameter when invoking some of the
<code>circular_buffer</code>'s methods e.g.
<code>insert(iterator pos, const value_type& item = %value_type())</code>. And
- <a href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a> and/or
+ <a href="https://www.boost.org/sgi/stl/EqualityComparable.html">EqualityComparable</a> and/or
<a href="../../../utility/LessThanComparable.html">LessThanComparable</a> if the <code>circular_buffer</code>
will be compared with another container.
\tparam Alloc The allocator type used for all internal memory management.
@@ -146,7 +146,7 @@ public:
//! An array range.
/*!
- (A typedef for the <a href="http://www.sgi.com/tech/stl/pair.html"><code>std::pair</code></a> where
+ (A typedef for the <a href="https://www.boost.org/sgi/stl/pair.html"><code>std::pair</code></a> where
its first element is a pointer to a beginning of an array and its second element represents
a size of the array.)
*/
@@ -154,7 +154,7 @@ public:
//! A range of a const array.
/*!
- (A typedef for the <a href="http://www.sgi.com/tech/stl/pair.html"><code>std::pair</code></a> where
+ (A typedef for the <a href="https://www.boost.org/sgi/stl/pair.html"><code>std::pair</code></a> where
its first element is a pointer to a beginning of a const array and its second element represents
a size of the const array.)
*/
@@ -711,7 +711,7 @@ public:
//! Rotate elements in the <code>circular_buffer</code>.
/*!
A more effective implementation of
- <code><a href="http://www.sgi.com/tech/stl/rotate.html">std::rotate</a></code>.
+ <code><a href="https://www.boost.org/sgi/stl/rotate.html">std::rotate</a></code>.
\pre <code>new_begin</code> is a valid iterator pointing to the <code>circular_buffer</code> <b>except</b> its
end.
\post Before calling the method suppose:<br><br>
@@ -733,7 +733,7 @@ public:
<code>circular_buffer</code> is full.
\par Complexity
Linear (in <code>(std::min)(m, n)</code>); constant if the <code>circular_buffer</code> is full.
- \sa <code><a href="http://www.sgi.com/tech/stl/rotate.html">std::rotate</a></code>
+ \sa <code><a href="https://www.boost.org/sgi/stl/rotate.html">std::rotate</a></code>
*/
void rotate(const_iterator new_begin) {
BOOST_CB_ASSERT(new_begin.is_valid(this)); // check for uninitialized or invalidated iterator
@@ -1131,7 +1131,7 @@ public:
/*!
\pre Valid range <code>[first, last)</code>.<br>
<code>first</code> and <code>last</code> have to meet the requirements of
- <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post <code>capacity() == std::distance(first, last) \&\& full() \&\& (*this)[0]== *first \&\&
(*this)[1] == *(first + 1) \&\& ... \&\& (*this)[std::distance(first, last) - 1] == *(last - 1)</code>
\param first The beginning of the range to be copied.
@@ -1153,7 +1153,7 @@ public:
/*!
\pre Valid range <code>[first, last)</code>.<br>
<code>first</code> and <code>last</code> have to meet the requirements of
- <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post <code>capacity() == buffer_capacity \&\& size() \<= std::distance(first, last) \&\&
(*this)[0]== *(last - buffer_capacity) \&\& (*this)[1] == *(last - buffer_capacity + 1) \&\& ... \&\&
(*this)[buffer_capacity - 1] == *(last - 1)</code><br><br>
@@ -1170,7 +1170,7 @@ public:
\par Complexity
Linear (in <code>std::distance(first, last)</code>; in
<code>min[capacity, std::distance(first, last)]</code> if the <code>InputIterator</code> is a
- <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
+ <a href="https://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
*/
template <class InputIterator>
circular_buffer(capacity_type buffer_capacity, InputIterator first, InputIterator last,
@@ -1316,7 +1316,7 @@ public:
specified range.
\pre Valid range <code>[first, last)</code>.<br>
<code>first</code> and <code>last</code> have to meet the requirements of
- <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post <code>capacity() == std::distance(first, last) \&\& size() == std::distance(first, last) \&\&
(*this)[0]== *first \&\& (*this)[1] == *(first + 1) \&\& ... \&\& (*this)[std::distance(first, last) - 1]
== *(last - 1)</code>
@@ -1349,7 +1349,7 @@ public:
<code>circular_buffer</code> will be removed and replaced with copies of elements from the specified range.
\pre Valid range <code>[first, last)</code>.<br>
<code>first</code> and <code>last</code> have to meet the requirements of
- <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post <code>capacity() == buffer_capacity \&\& size() \<= std::distance(first, last) \&\&
(*this)[0]== *(last - buffer_capacity) \&\& (*this)[1] == *(last - buffer_capacity + 1) \&\& ... \&\&
(*this)[buffer_capacity - 1] == *(last - 1)</code><br><br>
@@ -1370,7 +1370,7 @@ public:
\par Complexity
Linear (in <code>std::distance(first, last)</code>; in
<code>min[capacity, std::distance(first, last)]</code> if the <code>InputIterator</code> is a
- <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
+ <a href="https://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
\sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
@@ -1414,6 +1414,7 @@ public:
// push and pop
private:
+ /*! INTERNAL ONLY */
template <class ValT>
void push_back_impl(ValT item) {
if (full()) {
@@ -1429,6 +1430,7 @@ private:
}
}
+ /*! INTERNAL ONLY */
template <class ValT>
void push_front_impl(ValT item) {
BOOST_TRY {
@@ -1621,6 +1623,7 @@ public:
--m_size;
}
private:
+ /*! INTERNAL ONLY */
template <class ValT>
iterator insert_impl(iterator pos, ValT item) {
BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
@@ -1791,7 +1794,7 @@ public:
/*!
\pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.<br>
Valid range <code>[first, last)</code> where <code>first</code> and <code>last</code> meet the
- requirements of an <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ requirements of an <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post Elements from the range
<code>[first + max[0, distance(first, last) - (pos - begin()) - reserve()], last)</code> will be
inserted at the position <code>pos</code>.<br>The number of <code>min[pos - begin(), max[0,
@@ -1814,7 +1817,7 @@ public:
Linear (in <code>[std::distance(pos, end()) + std::distance(first, last)]</code>; in
<code>min[capacity(), std::distance(pos, end()) + std::distance(first, last)]</code> if the
<code>InputIterator</code> is a
- <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
+ <a href="https://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
\par Example
Consider a <code>circular_buffer</code> with the capacity of 6 and the size of 4. Its internal buffer may
look like the one below.<br><br>
@@ -1840,6 +1843,7 @@ public:
}
private:
+ /*! INTERNAL ONLY */
template <class ValT>
iterator rinsert_impl(iterator pos, ValT item) {
BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
@@ -2035,7 +2039,7 @@ public:
/*!
\pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.<br>
Valid range <code>[first, last)</code> where <code>first</code> and <code>last</code> meet the
- requirements of an <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ requirements of an <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post Elements from the range
<code>[first, last - max[0, distance(first, last) - (end() - pos) - reserve()])</code> will be inserted
before the position <code>pos</code>.<br>The number of <code>min[end() - pos, max[0,
@@ -2057,7 +2061,7 @@ public:
Linear (in <code>[std::distance(begin(), pos) + std::distance(first, last)]</code>; in
<code>min[capacity(), std::distance(begin(), pos) + std::distance(first, last)]</code> if the
<code>InputIterator</code> is a
- <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
+ <a href="https://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
\par Example
Consider a <code>circular_buffer</code> with the capacity of 6 and the size of 4. Its internal buffer may
look like the one below.<br><br>
@@ -2332,20 +2336,20 @@ public:
private:
// Helper methods
- //! Check if the <code>index</code> is valid.
+ /*! INTERNAL ONLY */
void check_position(size_type index) const {
if (index >= size())
throw_exception(std::out_of_range("circular_buffer"));
}
- //! Increment the pointer.
+ /*! INTERNAL ONLY */
template <class Pointer>
void increment(Pointer& p) const {
if (++p == m_end)
p = m_buff;
}
- //! Decrement the pointer.
+ /*! INTERNAL ONLY */
template <class Pointer>
void decrement(Pointer& p) const {
if (p == m_buff)
@@ -2353,30 +2357,32 @@ private:
--p;
}
- //! Add <code>n</code> to the pointer.
+ /*! INTERNAL ONLY */
template <class Pointer>
Pointer add(Pointer p, difference_type n) const {
- return p + (n < (m_end - p) ? n : n - capacity());
+ return p + (n < (m_end - p) ? n : n - (m_end - m_buff));
}
- //! Subtract <code>n</code> from the pointer.
+ /*! INTERNAL ONLY */
template <class Pointer>
Pointer sub(Pointer p, difference_type n) const {
- return p - (n > (p - m_buff) ? n - capacity() : n);
+ return p - (n > (p - m_buff) ? n - (m_end - m_buff) : n);
}
- //! Map the null pointer to virtual end of circular buffer.
+ /*! INTERNAL ONLY */
pointer map_pointer(pointer p) const { return p == 0 ? m_last : p; }
+ /*! INTERNAL ONLY */
const Alloc& alloc() const {
return base::get();
}
+ /*! INTERNAL ONLY */
Alloc& alloc() {
return base::get();
}
- //! Allocate memory.
+ /*! INTERNAL ONLY */
pointer allocate(size_type n) {
if (n > max_size())
throw_exception(std::length_error("circular_buffer"));
@@ -2389,18 +2395,20 @@ private:
#endif
}
- //! Deallocate memory.
+ /*! INTERNAL ONLY */
void deallocate(pointer p, size_type n) {
if (p != 0)
alloc().deallocate(p, n);
}
- //! Does the pointer point to the uninitialized memory?
+ /*! INTERNAL ONLY */
bool is_uninitialized(const_pointer p) const BOOST_NOEXCEPT {
- return p >= m_last && (m_first < m_last || p < m_first);
+ return (m_first < m_last)
+ ? (p >= m_last || p < m_first)
+ : (p >= m_last && p < m_first);
}
- //! Replace an element.
+ /*! INTERNAL ONLY */
void replace(pointer pos, param_value_type item) {
*pos = item;
#if BOOST_CB_ENABLE_DEBUG
@@ -2408,7 +2416,7 @@ private:
#endif
}
- //! Replace an element.
+ /*! INTERNAL ONLY */
void replace(pointer pos, rvalue_type item) {
*pos = boost::move(item);
#if BOOST_CB_ENABLE_DEBUG
@@ -2416,11 +2424,7 @@ private:
#endif
}
- //! Construct or replace an element.
- /*!
- <code>construct</code> has to be set to <code>true</code> if and only if
- <code>pos</code> points to an uninitialized memory.
- */
+ /*! INTERNAL ONLY */
void construct_or_replace(bool construct, pointer pos, param_value_type item) {
if (construct)
cb_details::allocator_traits<Alloc>::construct(alloc(), boost::to_address(pos), item);
@@ -2428,11 +2432,7 @@ private:
replace(pos, item);
}
- //! Construct or replace an element.
- /*!
- <code>construct</code> has to be set to <code>true</code> if and only if
- <code>pos</code> points to an uninitialized memory.
- */
+ /*! INTERNAL ONLY */
void construct_or_replace(bool construct, pointer pos, rvalue_type item) {
if (construct)
cb_details::allocator_traits<Alloc>::construct(alloc(), boost::to_address(pos), boost::move(item));
@@ -2440,7 +2440,7 @@ private:
replace(pos, boost::move(item));
}
- //! Destroy an item.
+ /*! INTERNAL ONLY */
void destroy_item(pointer p) {
cb_details::allocator_traits<Alloc>::destroy(alloc(), boost::to_address(p));
#if BOOST_CB_ENABLE_DEBUG
@@ -2449,13 +2449,13 @@ private:
#endif
}
- //! Destroy an item only if it has been constructed.
+ /*! INTERNAL ONLY */
void destroy_if_constructed(pointer pos) {
if (is_uninitialized(pos))
destroy_item(pos);
}
- //! Destroy the whole content of the circular buffer.
+ /*! INTERNAL ONLY */
void destroy_content() {
#if BOOST_CB_ENABLE_DEBUG
destroy_content(false_type());
@@ -2464,18 +2464,18 @@ private:
#endif
}
- //! Specialized destroy_content method.
+ /*! INTERNAL ONLY */
void destroy_content(const true_type&) {
m_first = add(m_first, size());
}
- //! Specialized destroy_content method.
+ /*! INTERNAL ONLY */
void destroy_content(const false_type&) {
for (size_type ii = 0; ii < size(); ++ii, increment(m_first))
destroy_item(m_first);
}
- //! Destroy content and free allocated memory.
+ /*! INTERNAL ONLY */
void destroy() BOOST_NOEXCEPT {
destroy_content();
deallocate(m_buff, capacity());
@@ -2487,13 +2487,13 @@ private:
#endif
}
- //! Initialize the internal buffer.
+ /*! INTERNAL ONLY */
void initialize_buffer(capacity_type buffer_capacity) {
m_buff = allocate(buffer_capacity);
m_end = m_buff + buffer_capacity;
}
- //! Initialize the internal buffer.
+ /*! INTERNAL ONLY */
void initialize_buffer(capacity_type buffer_capacity, param_value_type item) {
initialize_buffer(buffer_capacity);
BOOST_TRY {
@@ -2505,7 +2505,7 @@ private:
BOOST_CATCH_END
}
- //! Specialized initialize method.
+ /*! INTERNAL ONLY */
template <class IntegralType>
void initialize(IntegralType n, IntegralType item, const true_type&) {
m_size = static_cast<size_type>(n);
@@ -2513,7 +2513,7 @@ private:
m_first = m_last = m_buff;
}
- //! Specialized initialize method.
+ /*! INTERNAL ONLY */
template <class Iterator>
void initialize(Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
@@ -2524,7 +2524,7 @@ private:
#endif
}
- //! Specialized initialize method.
+ /*! INTERNAL ONLY */
template <class InputIterator>
void initialize(InputIterator first, InputIterator last, const std::input_iterator_tag&) {
BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS // check if the STL provides templated iterator constructors
@@ -2534,7 +2534,7 @@ private:
initialize(distance, boost::make_move_iterator(tmp.begin()), boost::make_move_iterator(tmp.end()), distance);
}
- //! Specialized initialize method.
+ /*! INTERNAL ONLY */
template <class ForwardIterator>
void initialize(ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) {
BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
@@ -2542,7 +2542,7 @@ private:
initialize(distance, first, last, distance);
}
- //! Specialized initialize method.
+ /*! INTERNAL ONLY */
template <class IntegralType>
void initialize(capacity_type buffer_capacity, IntegralType n, IntegralType item, const true_type&) {
BOOST_CB_ASSERT(buffer_capacity >= static_cast<size_type>(n)); // check for capacity lower than n
@@ -2552,7 +2552,7 @@ private:
m_last = buffer_capacity == size() ? m_buff : m_buff + size();
}
- //! Specialized initialize method.
+ /*! INTERNAL ONLY */
template <class Iterator>
void initialize(capacity_type buffer_capacity, Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
@@ -2563,7 +2563,7 @@ private:
#endif
}
- //! Specialized initialize method.
+ /*! INTERNAL ONLY */
template <class InputIterator>
void initialize(capacity_type buffer_capacity,
InputIterator first,
@@ -2586,7 +2586,7 @@ private:
}
}
- //! Specialized initialize method.
+ /*! INTERNAL ONLY */
template <class ForwardIterator>
void initialize(capacity_type buffer_capacity,
ForwardIterator first,
@@ -2596,7 +2596,7 @@ private:
initialize(buffer_capacity, first, last, std::distance(first, last));
}
- //! Initialize the circular buffer.
+ /*! INTERNAL ONLY */
template <class ForwardIterator>
void initialize(capacity_type buffer_capacity,
ForwardIterator first,
@@ -2621,7 +2621,7 @@ private:
m_last = m_buff;
}
- //! Reset the circular buffer.
+ /*! INTERNAL ONLY */
void reset(pointer buff, pointer last, capacity_type new_capacity) {
destroy();
m_size = last - buff;
@@ -2630,23 +2630,23 @@ private:
m_last = last == m_end ? m_buff : last;
}
- //! Specialized method for swapping the allocator.
+ /*! INTERNAL ONLY */
void swap_allocator(circular_buffer<T, Alloc>&, const true_type&) {
// Swap is not needed because allocators have no state.
}
- //! Specialized method for swapping the allocator.
+ /*! INTERNAL ONLY */
void swap_allocator(circular_buffer<T, Alloc>& cb, const false_type&) {
adl_move_swap(alloc(), cb.alloc());
}
- //! Specialized assign method.
+ /*! INTERNAL ONLY */
template <class IntegralType>
void assign(IntegralType n, IntegralType item, const true_type&) {
assign(static_cast<size_type>(n), static_cast<value_type>(item));
}
- //! Specialized assign method.
+ /*! INTERNAL ONLY */
template <class Iterator>
void assign(Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
@@ -2657,7 +2657,7 @@ private:
#endif
}
- //! Specialized assign method.
+ /*! INTERNAL ONLY */
template <class InputIterator>
void assign(InputIterator first, InputIterator last, const std::input_iterator_tag&) {
BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS // check if the STL provides templated iterator constructors
@@ -2669,7 +2669,7 @@ private:
(boost::make_move_iterator(tmp.begin()), boost::make_move_iterator(tmp.end()), alloc()));
}
- //! Specialized assign method.
+ /*! INTERNAL ONLY */
template <class ForwardIterator>
void assign(ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) {
BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
@@ -2677,13 +2677,13 @@ private:
assign_n(distance, distance, cb_details::make_assign_range(first, last, alloc()));
}
- //! Specialized assign method.
+ /*! INTERNAL ONLY */
template <class IntegralType>
void assign(capacity_type new_capacity, IntegralType n, IntegralType item, const true_type&) {
assign(new_capacity, static_cast<size_type>(n), static_cast<value_type>(item));
}
- //! Specialized assign method.
+ /*! INTERNAL ONLY */
template <class Iterator>
void assign(capacity_type new_capacity, Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
@@ -2694,7 +2694,7 @@ private:
#endif
}
- //! Specialized assign method.
+ /*! INTERNAL ONLY */
template <class InputIterator>
void assign(capacity_type new_capacity, InputIterator first, InputIterator last, const std::input_iterator_tag&) {
if (new_capacity == capacity()) {
@@ -2706,7 +2706,7 @@ private:
}
}
- //! Specialized assign method.
+ /*! INTERNAL ONLY */
template <class ForwardIterator>
void assign(capacity_type new_capacity, ForwardIterator first, ForwardIterator last,
const std::forward_iterator_tag&) {
@@ -2720,7 +2720,7 @@ private:
cb_details::make_assign_range(first, last, alloc()));
}
- //! Helper assign method.
+ /*! INTERNAL ONLY */
template <class Functor>
void assign_n(capacity_type new_capacity, size_type n, const Functor& fnc) {
if (new_capacity == capacity()) {
@@ -2750,7 +2750,7 @@ private:
m_last = add(m_buff, size());
}
- //! Helper insert method.
+ /*! INTERNAL ONLY */
template <class ValT>
iterator insert_item(const iterator& pos, ValT item) {
pointer p = pos.m_it;
@@ -2786,13 +2786,13 @@ private:
return iterator(this, p);
}
- //! Specialized insert method.
+ /*! INTERNAL ONLY */
template <class IntegralType>
void insert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) {
insert(pos, static_cast<size_type>(n), static_cast<value_type>(item));
}
- //! Specialized insert method.
+ /*! INTERNAL ONLY */
template <class Iterator>
void insert(const iterator& pos, Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
@@ -2803,7 +2803,7 @@ private:
#endif
}
- //! Specialized insert method.
+ /*! INTERNAL ONLY */
template <class InputIterator>
void insert(iterator pos, InputIterator first, InputIterator last, const std::input_iterator_tag&) {
if (!full() || pos != begin()) {
@@ -2812,7 +2812,7 @@ private:
}
}
- //! Specialized insert method.
+ /*! INTERNAL ONLY */
template <class ForwardIterator>
void insert(const iterator& pos, ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) {
BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
@@ -2829,7 +2829,7 @@ private:
insert_n(pos, n, cb_details::iterator_wrapper<ForwardIterator>(first));
}
- //! Helper insert method.
+ /*! INTERNAL ONLY */
template <class Wrapper>
void insert_n(const iterator& pos, size_type n, const Wrapper& wrapper) {
size_type construct = reserve();
@@ -2877,13 +2877,13 @@ private:
m_size += construct;
}
- //! Specialized rinsert method.
+ /*! INTERNAL ONLY */
template <class IntegralType>
void rinsert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) {
rinsert(pos, static_cast<size_type>(n), static_cast<value_type>(item));
}
- //! Specialized rinsert method.
+ /*! INTERNAL ONLY */
template <class Iterator>
void rinsert(const iterator& pos, Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
@@ -2894,7 +2894,7 @@ private:
#endif
}
- //! Specialized insert method.
+ /*! INTERNAL ONLY */
template <class InputIterator>
void rinsert(iterator pos, InputIterator first, InputIterator last, const std::input_iterator_tag&) {
if (!full() || pos.m_it != 0) {
@@ -2906,14 +2906,14 @@ private:
}
}
- //! Specialized rinsert method.
+ /*! INTERNAL ONLY */
template <class ForwardIterator>
void rinsert(const iterator& pos, ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) {
BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
rinsert_n(pos, std::distance(first, last), cb_details::iterator_wrapper<ForwardIterator>(first));
}
- //! Helper rinsert method.
+ /*! INTERNAL ONLY */
template <class Wrapper>
void rinsert_n(const iterator& pos, size_type n, const Wrapper& wrapper) {
if (n == 0)
@@ -2966,25 +2966,25 @@ private:
m_size += construct;
}
- //! Specialized erase_begin method.
+ /*! INTERNAL ONLY */
void erase_begin(size_type n, const true_type&) {
m_first = add(m_first, n);
m_size -= n;
}
- //! Specialized erase_begin method.
+ /*! INTERNAL ONLY */
void erase_begin(size_type n, const false_type&) {
iterator b = begin();
rerase(b, b + n);
}
- //! Specialized erase_end method.
+ /*! INTERNAL ONLY */
void erase_end(size_type n, const true_type&) {
m_last = sub(m_last, n);
m_size -= n;
}
- //! Specialized erase_end method.
+ /*! INTERNAL ONLY */
void erase_end(size_type n, const false_type&) {
iterator e = end();
erase(e - n, e);
@@ -2998,7 +2998,7 @@ private:
\param lhs The <code>circular_buffer</code> to compare.
\param rhs The <code>circular_buffer</code> to compare.
\return <code>lhs.\link circular_buffer::size() size()\endlink == rhs.\link circular_buffer::size() size()\endlink
- && <a href="http://www.sgi.com/tech/stl/equal.html">std::equal</a>(lhs.\link circular_buffer::begin()
+ && <a href="https://www.boost.org/sgi/stl/equal.html">std::equal</a>(lhs.\link circular_buffer::begin()
begin()\endlink, lhs.\link circular_buffer::end() end()\endlink,
rhs.\link circular_buffer::begin() begin()\endlink)</code>
\throws Nothing.
@@ -3017,7 +3017,7 @@ inline bool operator == (const circular_buffer<T, Alloc>& lhs, const circular_bu
right one.
\param lhs The <code>circular_buffer</code> to compare.
\param rhs The <code>circular_buffer</code> to compare.
- \return <code><a href="http://www.sgi.com/tech/stl/lexicographical_compare.html">
+ \return <code><a href="https://www.boost.org/sgi/stl/lexicographical_compare.html">
std::lexicographical_compare</a>(lhs.\link circular_buffer::begin() begin()\endlink,
lhs.\link circular_buffer::end() end()\endlink, rhs.\link circular_buffer::begin() begin()\endlink,
rhs.\link circular_buffer::end() end()\endlink)</code>
diff --git a/boost/circular_buffer/space_optimized.hpp b/boost/circular_buffer/space_optimized.hpp
index 73d60c4f80..34dbd9b923 100644
--- a/boost/circular_buffer/space_optimized.hpp
+++ b/boost/circular_buffer/space_optimized.hpp
@@ -453,7 +453,7 @@ public:
/*!
\pre Valid range <code>[first, last)</code>.<br>
<code>first</code> and <code>last</code> have to meet the requirements of
- <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post <code>capacity().%capacity() == std::distance(first, last) \&\& capacity().min_capacity() == 0 \&\&
full() \&\& (*this)[0]== *first \&\& (*this)[1] == *(first + 1) \&\& ... \&\&
(*this)[std::distance(first, last) - 1] == *(last - 1)</code><br><br>
@@ -478,7 +478,7 @@ public:
of allocated memory) filled with a copy of the range.
\pre Valid range <code>[first, last)</code>.<br>
<code>first</code> and <code>last</code> have to meet the requirements of
- <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post <code>capacity() == capacity_ctrl \&\& size() \<= std::distance(first, last) \&\& (*this)[0]==
*(last - capacity_ctrl.%capacity()) \&\& (*this)[1] == *(last - capacity_ctrl.%capacity() + 1) \&\& ...
\&\& (*this)[capacity_ctrl.%capacity() - 1] == *(last - 1)</code><br><br>
@@ -499,7 +499,7 @@ public:
\par Complexity
Linear (in <code>std::distance(first, last)</code>; in
<code>min[capacity_ctrl.%capacity(), std::distance(first, last)]</code> if the <code>InputIterator</code>
- is a <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
+ is a <a href="https://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
*/
template <class InputIterator>
circular_buffer_space_optimized(capacity_type capacity_ctrl, InputIterator first, InputIterator last,
@@ -655,7 +655,7 @@ public:
elements from the specified range.
\pre Valid range <code>[first, last)</code>.<br>
<code>first</code> and <code>last</code> have to meet the requirements of
- <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post <code>capacity().%capacity() == std::distance(first, last) \&\& capacity().min_capacity() == 0 \&\&
size() == std::distance(first, last) \&\& (*this)[0]== *first \&\& (*this)[1] == *(first + 1) \&\& ...
\&\& (*this)[std::distance(first, last) - 1] == *(last - 1)</code><br><br>
@@ -692,7 +692,7 @@ public:
elements from the specified range.
\pre Valid range <code>[first, last)</code>.<br>
<code>first</code> and <code>last</code> have to meet the requirements of
- <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post <code>capacity() == capacity_ctrl \&\& size() \<= std::distance(first, last) \&\&
(*this)[0]== *(last - capacity) \&\& (*this)[1] == *(last - capacity + 1) \&\& ... \&\&
(*this)[capacity - 1] == *(last - 1)</code><br><br>
@@ -715,7 +715,7 @@ public:
\par Complexity
Linear (in <code>std::distance(first, last)</code>; in
<code>min[capacity_ctrl.%capacity(), std::distance(first, last)]</code> if the <code>InputIterator</code>
- is a <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
+ is a <a href="https://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
\sa <code>\link operator=(const circular_buffer_space_optimized&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
@@ -1114,7 +1114,7 @@ public:
/*!
\pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer_space_optimized</code> or its
end.<br>Valid range <code>[first, last)</code> where <code>first</code> and <code>last</code> meet the
- requirements of an <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ requirements of an <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post Elements from the range
<code>[first + max[0, distance(first, last) - (pos - begin()) - reserve()], last)</code> will be
inserted at the position <code>pos</code>.<br>The number of <code>min[pos - begin(), max[0,
@@ -1136,7 +1136,7 @@ public:
Linear (in <code>[size() + std::distance(first, last)]</code>; in
<code>min[capacity().%capacity(), size() + std::distance(first, last)]</code> if the
<code>InputIterator</code> is a
- <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
+ <a href="https://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
\par Example
Consider a <code>circular_buffer_space_optimized</code> with the capacity of 6 and the size of 4. Its
internal buffer may look like the one below.<br><br>
@@ -1326,7 +1326,7 @@ public:
\pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer_space_optimized</code> or its
end.<br>
Valid range <code>[first, last)</code> where <code>first</code> and <code>last</code> meet the
- requirements of an <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
+ requirements of an <a href="https://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>.
\post Elements from the range
<code>[first, last - max[0, distance(first, last) - (end() - pos) - reserve()])</code> will be inserted
before the position <code>pos</code>.<br>The number of <code>min[end() - pos, max[0,
@@ -1349,7 +1349,7 @@ public:
Linear (in <code>[size() + std::distance(first, last)]</code>; in
<code>min[capacity().%capacity(), size() + std::distance(first, last)]</code> if the
<code>InputIterator</code> is a
- <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
+ <a href="https://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
\par Example
Consider a <code>circular_buffer_space_optimized</code> with the capacity of 6 and the size of 4. Its
internal buffer may look like the one below.<br><br>
@@ -1522,7 +1522,7 @@ public:
private:
// Helper methods
- //! Adjust the amount of allocated memory.
+ /*! INTERNAL ONLY */
void adjust_min_capacity() {
if (m_capacity_ctrl.min_capacity() > circular_buffer<T, Alloc>::capacity())
circular_buffer<T, Alloc>::set_capacity(m_capacity_ctrl.min_capacity());
@@ -1530,7 +1530,7 @@ private:
check_high_capacity();
}
- //! Ensure the reserve for possible growth up.
+ /*! INTERNAL ONLY */
size_type ensure_reserve(size_type new_capacity, size_type buffer_size) const {
if (buffer_size + new_capacity / 5 >= new_capacity)
new_capacity *= 2; // ensure at least 20% reserve
@@ -1539,10 +1539,7 @@ private:
return new_capacity;
}
- //! Check for low capacity.
- /*
- \post If the capacity is low it will be increased.
- */
+ /*! INTERNAL ONLY */
void check_low_capacity(size_type n = 1) {
size_type new_size = size() + n;
size_type new_capacity = circular_buffer<T, Alloc>::capacity();
@@ -1558,10 +1555,7 @@ private:
#endif
}
- //! Check for high capacity.
- /*
- \post If the capacity is high it will be decreased.
- */
+ /*! INTERNAL ONLY */
void check_high_capacity() {
size_type new_capacity = circular_buffer<T, Alloc>::capacity();
while (new_capacity / 3 >= size()) { // (new_capacity / 3) -> avoid oscillations
@@ -1578,28 +1572,28 @@ private:
#endif
}
- //! Specialized method for reducing the capacity.
+ /*! INTERNAL ONLY */
void reduce_capacity(const true_type&) {
circular_buffer<T, Alloc>::set_capacity((std::max)(m_capacity_ctrl.min_capacity(), size()));
}
- //! Specialized method for reducing the capacity.
+ /*! INTERNAL ONLY */
void reduce_capacity(const false_type&) {}
- //! Determine the initial capacity.
+ /*! INTERNAL ONLY */
static size_type init_capacity(const capacity_type& capacity_ctrl, size_type n) {
BOOST_CB_ASSERT(capacity_ctrl.capacity() >= n); // check for capacity lower than n
return (std::max)(capacity_ctrl.min_capacity(), n);
}
- //! Specialized method for determining the initial capacity.
+ /*! INTERNAL ONLY */
template <class IntegralType>
static size_type init_capacity(const capacity_type& capacity_ctrl, IntegralType n, IntegralType,
const true_type&) {
return init_capacity(capacity_ctrl, static_cast<size_type>(n));
}
- //! Specialized method for determining the initial capacity.
+ /*! INTERNAL ONLY */
template <class Iterator>
static size_type init_capacity(const capacity_type& capacity_ctrl, Iterator first, Iterator last,
const false_type&) {
@@ -1612,14 +1606,14 @@ private:
#endif
}
- //! Specialized method for determining the initial capacity.
+ /*! INTERNAL ONLY */
template <class InputIterator>
static size_type init_capacity(const capacity_type& capacity_ctrl, InputIterator, InputIterator,
const std::input_iterator_tag&) {
return capacity_ctrl.capacity();
}
- //! Specialized method for determining the initial capacity.
+ /*! INTERNAL ONLY */
template <class ForwardIterator>
static size_type init_capacity(const capacity_type& capacity_ctrl, ForwardIterator first, ForwardIterator last,
const std::forward_iterator_tag&) {
@@ -1628,13 +1622,13 @@ private:
(std::min)(capacity_ctrl.capacity(), static_cast<size_type>(std::distance(first, last))));
}
- //! Specialized insert method.
+ /*! INTERNAL ONLY */
template <class IntegralType>
void insert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) {
insert(pos, static_cast<size_type>(n), static_cast<value_type>(item));
}
- //! Specialized insert method.
+ /*! INTERNAL ONLY */
template <class Iterator>
void insert(const iterator& pos, Iterator first, Iterator last, const false_type&) {
size_type index = pos - begin();
@@ -1642,13 +1636,13 @@ private:
circular_buffer<T, Alloc>::insert(begin() + index, first, last);
}
- //! Specialized rinsert method.
+ /*! INTERNAL ONLY */
template <class IntegralType>
void rinsert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) {
rinsert(pos, static_cast<size_type>(n), static_cast<value_type>(item));
}
- //! Specialized rinsert method.
+ /*! INTERNAL ONLY */
template <class Iterator>
void rinsert(const iterator& pos, Iterator first, Iterator last, const false_type&) {
size_type index = pos - begin();
diff --git a/boost/config/auto_link.hpp b/boost/config/auto_link.hpp
index d0079d9bc2..e74f3c10e9 100644
--- a/boost/config/auto_link.hpp
+++ b/boost/config/auto_link.hpp
@@ -99,7 +99,8 @@ BOOST_LIB_VERSION: The Boost version, in the form x_y, for Boost version x.y.
#if defined(BOOST_MSVC) \
|| defined(__BORLANDC__) \
|| (defined(__MWERKS__) && defined(_WIN32) && (__MWERKS__ >= 0x3000)) \
- || (defined(__ICL) && defined(_MSC_EXTENSIONS) && (_MSC_VER >= 1200))
+ || (defined(__ICL) && defined(_MSC_EXTENSIONS) && (_MSC_VER >= 1200)) \
+ || (defined(BOOST_CLANG) && defined(BOOST_WINDOWS) && defined(_MSC_VER) && (__clang_major__ >= 4))
#ifndef BOOST_VERSION_HPP
# include <boost/version.hpp>
@@ -203,6 +204,11 @@ BOOST_LIB_VERSION: The Boost version, in the form x_y, for Boost version x.y.
// Metrowerks CodeWarrior 9.x
# define BOOST_LIB_TOOLSET "cw9"
+# elif defined(BOOST_CLANG) && defined(BOOST_WINDOWS) && defined(_MSC_VER) && (__clang_major__ >= 4)
+
+ // Clang on Windows
+# define BOOST_LIB_TOOLSET "clangw" BOOST_STRINGIZE(__clang_major__)
+
# endif
#endif // BOOST_LIB_TOOLSET
diff --git a/boost/config/compiler/gcc.hpp b/boost/config/compiler/gcc.hpp
index 9ae6072ee0..3380ffed19 100644
--- a/boost/config/compiler/gcc.hpp
+++ b/boost/config/compiler/gcc.hpp
@@ -309,8 +309,8 @@
# define BOOST_FALLTHROUGH __attribute__((fallthrough))
#endif
-#ifdef __MINGW32__
-// Currently (June 2017) thread_local is broken on mingw for all current compiler releases, see
+#if defined(__MINGW32__) && !defined(__MINGW64__)
+// Currently (March 2019) thread_local is broken on mingw for all current 32bit compiler releases, see
// https://sourceforge.net/p/mingw-w64/bugs/527/
// Not setting this causes program termination on thread exit.
#define BOOST_NO_CXX11_THREAD_LOCAL
@@ -327,7 +327,7 @@
//
// __builtin_unreachable:
-#if BOOST_GCC_VERSION >= 40800
+#if BOOST_GCC_VERSION >= 40500
#define BOOST_UNREACHABLE_RETURN(x) __builtin_unreachable();
#endif
diff --git a/boost/config/compiler/visualc.hpp b/boost/config/compiler/visualc.hpp
index 29642473cd..e2ea2702b9 100644
--- a/boost/config/compiler/visualc.hpp
+++ b/boost/config/compiler/visualc.hpp
@@ -43,6 +43,9 @@
# error "Compiler not supported or configured - please reconfigure"
#endif
+// VS2005 (VC8) docs: __assume has been in Visual C++ for multiple releases
+#define BOOST_UNREACHABLE_RETURN(x) __assume(0);
+
#if _MSC_FULL_VER < 180020827
# define BOOST_NO_FENV_H
#endif
@@ -202,8 +205,9 @@
#if (_MSC_VER < 1911) || (_MSVC_LANG < 201703)
# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
# define BOOST_NO_CXX17_IF_CONSTEXPR
-# define BOOST_NO_CXX17_HDR_OPTIONAL
-# define BOOST_NO_CXX17_HDR_STRING_VIEW
+// Let the defaults handle these now:
+//# define BOOST_NO_CXX17_HDR_OPTIONAL
+//# define BOOST_NO_CXX17_HDR_STRING_VIEW
#endif
// MSVC including version 14 has not yet completely
@@ -313,7 +317,7 @@
# endif
# else
# if _MSC_VER < 1200
- // Note: Versions up to 7.0 aren't supported.
+ // Note: Versions up to 10.0 aren't supported.
# define BOOST_COMPILER_VERSION 5.0
# elif _MSC_VER < 1300
# define BOOST_COMPILER_VERSION 6.0
@@ -335,6 +339,8 @@
# define BOOST_COMPILER_VERSION 14.0
# elif _MSC_VER < 1920
# define BOOST_COMPILER_VERSION 14.1
+# elif _MSC_VER < 1930
+# define BOOST_COMPILER_VERSION 14.2
# else
# define BOOST_COMPILER_VERSION _MSC_VER
# endif
@@ -346,8 +352,8 @@
#include <boost/config/pragma_message.hpp>
//
-// last known and checked version is 19.12.25830.2 (VC++ 2017.3):
-#if (_MSC_VER > 1912)
+// last known and checked version is 19.20.27508 (VC++ 2019 RC3):
+#if (_MSC_VER > 1920)
# if defined(BOOST_ASSERT_CONFIG)
# error "Boost.Config is older than your current compiler version."
# elif !defined(BOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE)
diff --git a/boost/config/detail/suffix.hpp b/boost/config/detail/suffix.hpp
index cee9647b6b..86f6081e05 100644
--- a/boost/config/detail/suffix.hpp
+++ b/boost/config/detail/suffix.hpp
@@ -992,6 +992,23 @@ namespace std{ using ::type_info; }
#ifndef BOOST_ATTRIBUTE_UNUSED
# define BOOST_ATTRIBUTE_UNUSED
#endif
+//
+// [[nodiscard]]:
+//
+#ifdef __has_cpp_attribute
+#if __has_cpp_attribute(nodiscard)
+# define BOOST_ATTRIBUTE_NODISCARD [[nodiscard]]
+#endif
+#if __has_cpp_attribute(no_unique_address) && !(defined(__GNUC__) && (__cplusplus < 201100))
+# define BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]]
+#endif
+#endif
+#ifndef BOOST_ATTRIBUTE_NODISCARD
+# define BOOST_ATTRIBUTE_NODISCARD
+#endif
+#ifndef BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS
+# define BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS
+#endif
#define BOOST_STATIC_CONSTEXPR static BOOST_CONSTEXPR_OR_CONST
@@ -1027,6 +1044,7 @@ namespace std{ using ::type_info; }
#if !defined(__has_include)
# define BOOST_NO_CXX17_HDR_OPTIONAL
# define BOOST_NO_CXX17_HDR_STRING_VIEW
+# define BOOST_NO_CXX17_HDR_VARIANT
#else
#if !__has_include(<optional>)
# define BOOST_NO_CXX17_HDR_OPTIONAL
@@ -1034,6 +1052,9 @@ namespace std{ using ::type_info; }
#if !__has_include(<string_view>)
# define BOOST_NO_CXX17_HDR_STRING_VIEW
#endif
+#if !__has_include(<variant>)
+# define BOOST_NO_CXX17_HDR_VARIANT
+#endif
#endif
//
diff --git a/boost/config/platform/vxworks.hpp b/boost/config/platform/vxworks.hpp
index a91e4ab439..7718acb638 100644
--- a/boost/config/platform/vxworks.hpp
+++ b/boost/config/platform/vxworks.hpp
@@ -12,40 +12,17 @@
// like (GCC 2.96) . Do not even think of getting this to work,
// a miserable failure will be guaranteed!
//
-// Equally, this file has been tested for RTPs (Real Time Processes)
-// only, not for DKMs (Downloadable Kernel Modules). These two types
-// of executables differ largely in the available functionality of
-// the C-library, STL, and so on. A DKM uses a C89 library with no
-// wide character support and no guarantee of ANSI C. The same Dinkum
+// VxWorks supports C++ linkage in the kernel with
+// DKMs (Downloadable Kernel Modules). But, until recently
+// the kernel used a C89 library with no
+// wide character support and no guarantee of ANSI C.
+// Regardless of the C library the same Dinkum
// STL library is used in both contexts.
//
// Similarly the Dinkum abridged STL that supports the loosely specified
// embedded C++ standard has not been tested and is unlikely to work
// on anything but the simplest library.
// ====================================================================
-//
-// Additional Configuration
-// -------------------------------------------------------------------
-//
-// Because of the ordering of include files and other issues the following
-// additional definitions worked better outside this file.
-//
-// When building the log library add the following to the b2 invocation
-// define=BOOST_LOG_WITHOUT_IPC
-// and
-// -DBOOST_LOG_WITHOUT_DEFAULT_FACTORIES
-// to your compile options.
-//
-// When building the test library add
-// -DBOOST_TEST_LIMITED_SIGNAL_DETAILS
-// to your compile options
-//
-// When building containers library add
-// -DHAVE_MORECORE=0
-// to your c compile options so dlmalloc heap library is compiled
-// without brk() calls
-//
-// ====================================================================
//
// Some important information regarding the usage of POSIX semaphores:
// -------------------------------------------------------------------
@@ -112,30 +89,20 @@
// --------------------------------
#define BOOST_PLATFORM "vxWorks"
-// Special behaviour for DKMs:
-#ifdef _WRS_KERNEL
- // DKMs do not have the <cwchar>-header,
- // but apparently they do have an intrinsic wchar_t meanwhile!
-# define BOOST_NO_CWCHAR
-
- // Lots of wide-functions and -headers are unavailable for DKMs as well:
-# define BOOST_NO_CWCTYPE
-# define BOOST_NO_SWPRINTF
-# define BOOST_NO_STD_WSTRING
-# define BOOST_NO_STD_WSTREAMBUF
-#endif
// Generally available headers:
#define BOOST_HAS_UNISTD_H
#define BOOST_HAS_STDINT_H
#define BOOST_HAS_DIRENT_H
-#define BOOST_HAS_SLIST
+//#define BOOST_HAS_SLIST
// vxWorks does not have installed an iconv-library by default,
// so unfortunately no Unicode support from scratch is available!
// Thus, instead it is suggested to switch to ICU, as this seems
// to be the most complete and portable option...
-#define BOOST_LOCALE_WITH_ICU
+#ifndef BOOST_LOCALE_WITH_ICU
+ #define BOOST_LOCALE_WITH_ICU
+#endif
// Generally available functionality:
#define BOOST_HAS_THREADS
@@ -170,16 +137,18 @@
# ifndef _POSIX_THREADS
# define _POSIX_THREADS 1
# endif
+// no sysconf( _SC_PAGESIZE) in kernel
+# define BOOST_THREAD_USES_GETPAGESIZE
#endif
#if (_WRS_VXWORKS_MAJOR < 7)
// vxWorks-around: <time.h> #defines CLOCKS_PER_SEC as sysClkRateGet() but
// miserably fails to #include the required <sysLib.h> to make
// sysClkRateGet() available! So we manually include it here.
-#ifdef __RTP__
-# include <time.h>
-# include <sysLib.h>
-#endif
+# ifdef __RTP__
+# include <time.h>
+# include <sysLib.h>
+# endif
// vxWorks-around: In <stdint.h> the macros INT32_C(), UINT32_C(), INT64_C() and
// UINT64_C() are defined erroneously, yielding not a signed/
@@ -188,30 +157,47 @@
// when trying to define several constants which do not fit into a
// long type! We correct them here by redefining.
-#include <cstdint>
+# include <cstdint>
+
+// Special behaviour for DKMs:
// Some macro-magic to do the job
-#define VX_JOIN(X, Y) VX_DO_JOIN(X, Y)
-#define VX_DO_JOIN(X, Y) VX_DO_JOIN2(X, Y)
-#define VX_DO_JOIN2(X, Y) X##Y
+# define VX_JOIN(X, Y) VX_DO_JOIN(X, Y)
+# define VX_DO_JOIN(X, Y) VX_DO_JOIN2(X, Y)
+# define VX_DO_JOIN2(X, Y) X##Y
// Correctly setup the macros
-#undef INT32_C
-#undef UINT32_C
-#undef INT64_C
-#undef UINT64_C
-#define INT32_C(x) VX_JOIN(x, L)
-#define UINT32_C(x) VX_JOIN(x, UL)
-#define INT64_C(x) VX_JOIN(x, LL)
-#define UINT64_C(x) VX_JOIN(x, ULL)
+# undef INT32_C
+# undef UINT32_C
+# undef INT64_C
+# undef UINT64_C
+# define INT32_C(x) VX_JOIN(x, L)
+# define UINT32_C(x) VX_JOIN(x, UL)
+# define INT64_C(x) VX_JOIN(x, LL)
+# define UINT64_C(x) VX_JOIN(x, ULL)
// #include Libraries required for the following function adaption
-#include <sys/time.h>
+# include <sys/time.h>
#endif // _WRS_VXWORKS_MAJOR < 7
#include <ioLib.h>
#include <tickLib.h>
+#if defined(_WRS_KERNEL) && (_CPPLIB_VER < 700)
+ // recent kernels use Dinkum clib v7.00+
+ // with widechar but older kernels
+ // do not have the <cwchar>-header,
+ // but apparently they do have an intrinsic wchar_t meanwhile!
+# define BOOST_NO_CWCHAR
+
+ // Lots of wide-functions and -headers are unavailable for DKMs as well:
+# define BOOST_NO_CWCTYPE
+# define BOOST_NO_SWPRINTF
+# define BOOST_NO_STD_WSTRING
+# define BOOST_NO_STD_WSTREAMBUF
+#endif
+
+
// Use C-linkage for the following helper functions
#ifdef __cplusplus
extern "C" {
@@ -253,9 +239,9 @@ inline int truncate(const char *p, off_t l){
}
#ifdef __GNUC__
-#define ___unused __attribute__((unused))
+# define ___unused __attribute__((unused))
#else
-#define ___unused
+# define ___unused
#endif
// Fake symlink handling by dummy functions:
@@ -291,7 +277,7 @@ inline int gettimeofday(struct timeval *tv, void * /*tzv*/) {
* to avoid conflict with MPL operator times
*/
#if (_WRS_VXWORKS_MAJOR < 7)
-#ifdef __cplusplus
+# ifdef __cplusplus
// vxWorks provides neither struct tms nor function times()!
// We implement an empty dummy-function, simply setting the user
@@ -327,7 +313,7 @@ struct tms{
namespace std {
using ::times;
}
-#endif // __cplusplus
+# endif // __cplusplus
#endif // _WRS_VXWORKS_MAJOR < 7
@@ -336,16 +322,16 @@ extern "C" void bzero (void *, size_t); // FD_ZERO uses bzero() but does
// Put the selfmade functions into the std-namespace, just in case
namespace std {
-# ifdef __RTP__
+# ifdef __RTP__
using ::getrlimit;
using ::setrlimit;
-# endif
+# endif
using ::truncate;
using ::symlink;
using ::readlink;
-#if (_WRS_VXWORKS_MAJOR < 7)
+# if (_WRS_VXWORKS_MAJOR < 7)
using ::gettimeofday;
-#endif
+# endif
}
#endif // __cplusplus
@@ -355,10 +341,12 @@ namespace std {
// Include signal.h which might contain a typo to be corrected here
#include <signal.h>
+
#if (_WRS_VXWORKS_MAJOR < 7)
-#define getpagesize() sysconf(_SC_PAGESIZE) // getpagesize is deprecated anyway!
+# define getpagesize() sysconf(_SC_PAGESIZE) // getpagesize is deprecated anyway!
inline int lstat(p, b) { return stat(p, b); } // lstat() == stat(), as vxWorks has no symlinks!
#endif
+
#ifndef S_ISSOCK
# define S_ISSOCK(mode) ((mode & S_IFMT) == S_IFSOCK) // Is file a socket?
#endif
@@ -379,7 +367,7 @@ typedef int locale_t; // locale_t is a POSIX-ex
// vxWorks 7 adds C++11 support
// however it is optional, and does not match exactly the support determined
// by examining the Dinkum STL version and GCC version (or ICC and DCC)
-#ifndef _WRS_CONFIG_LANG_LIB_CPLUS_CPLUS_USER_2011
+#if !( defined( _WRS_CONFIG_LANG_LIB_CPLUS_CPLUS_USER_2011) || defined(_WRS_CONFIG_LIBCPLUS_STD))
# define BOOST_NO_CXX11_ADDRESSOF // C11 addressof operator on memory location
# define BOOST_NO_CXX11_ALLOCATOR
# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
@@ -408,9 +396,9 @@ typedef int locale_t; // locale_t is a POSIX-ex
# define BOOST_NO_CXX11_HDR_UNORDERED_MAP
# define BOOST_NO_CXX11_HDR_UNORDERED_SET
#else
-#ifndef BOOST_SYSTEM_NO_DEPRECATED
-# define BOOST_SYSTEM_NO_DEPRECATED // workaround link error in spirit
-#endif
+# ifndef BOOST_SYSTEM_NO_DEPRECATED
+# define BOOST_SYSTEM_NO_DEPRECATED // workaround link error in spirit
+# endif
#endif
@@ -418,6 +406,8 @@ typedef int locale_t; // locale_t is a POSIX-ex
#undef NONE
// restrict is an iostreams class
#undef restrict
+// affects some typeof tests
+#undef V7
// use fake poll() from Unix layer in ASIO to get full functionality
// most libraries will use select() but this define allows 'iostream' functionality
@@ -430,4 +420,3 @@ typedef int locale_t; // locale_t is a POSIX-ex
# define BOOST_ASIO_DISABLE_SERIAL_PORT
#endif
-
diff --git a/boost/config/stdlib/dinkumware.hpp b/boost/config/stdlib/dinkumware.hpp
index e829f08e51..19c772c124 100644
--- a/boost/config/stdlib/dinkumware.hpp
+++ b/boost/config/stdlib/dinkumware.hpp
@@ -174,6 +174,9 @@
#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650) || !defined(BOOST_MSVC) || (BOOST_MSVC < 1910) || !defined(_HAS_CXX17) || (_HAS_CXX17 == 0)
# define BOOST_NO_CXX17_STD_APPLY
# define BOOST_NO_CXX17_ITERATOR_TRAITS
+# define BOOST_NO_CXX17_HDR_STRING_VIEW
+# define BOOST_NO_CXX17_HDR_OPTIONAL
+# define BOOST_NO_CXX17_HDR_VARIANT
#endif
#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650) || !defined(_HAS_CXX17) || (_HAS_CXX17 == 0) || !defined(_MSVC_STL_UPDATE) || (_MSVC_STL_UPDATE < 201709)
# define BOOST_NO_CXX17_STD_INVOKE
diff --git a/boost/config/stdlib/libcpp.hpp b/boost/config/stdlib/libcpp.hpp
index ffe2f2a0f5..e5e5c349e0 100644
--- a/boost/config/stdlib/libcpp.hpp
+++ b/boost/config/stdlib/libcpp.hpp
@@ -91,6 +91,7 @@
# define BOOST_NO_CXX17_STD_APPLY
# define BOOST_NO_CXX17_HDR_OPTIONAL
# define BOOST_NO_CXX17_HDR_STRING_VIEW
+# define BOOST_NO_CXX17_HDR_VARIANT
#endif
#if (_LIBCPP_VERSION > 4000) && (__cplusplus > 201402L) && !defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
# define BOOST_NO_AUTO_PTR
diff --git a/boost/config/stdlib/libstdcpp3.hpp b/boost/config/stdlib/libstdcpp3.hpp
index 38209ddd45..9696515c53 100644
--- a/boost/config/stdlib/libstdcpp3.hpp
+++ b/boost/config/stdlib/libstdcpp3.hpp
@@ -301,6 +301,7 @@ extern "C" char *gets (char *__s);
# define BOOST_NO_CXX17_STD_APPLY
# define BOOST_NO_CXX17_HDR_OPTIONAL
# define BOOST_NO_CXX17_HDR_STRING_VIEW
+# define BOOST_NO_CXX17_HDR_VARIANT
#endif
#if defined(__has_include)
diff --git a/boost/container/adaptive_pool.hpp b/boost/container/adaptive_pool.hpp
index d1d77bcade..8fcc1261d1 100644
--- a/boost/container/adaptive_pool.hpp
+++ b/boost/container/adaptive_pool.hpp
@@ -146,13 +146,13 @@ class adaptive_pool
//!Returns the number of elements that could be allocated.
//!Never throws
size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
- { return size_type(-1)/sizeof(T); }
+ { return size_type(-1)/(2u*sizeof(T)); }
//!Allocate memory for an array of count elements.
//!Throws std::bad_alloc if there is no enough memory
pointer allocate(size_type count, const void * = 0)
{
- if(BOOST_UNLIKELY(count > this->max_size()))
+ if(BOOST_UNLIKELY(count > size_type(-1)/(2u*sizeof(T))))
boost::container::throw_bad_alloc();
if(Version == 1 && count == 1){
@@ -456,13 +456,13 @@ class private_adaptive_pool
//!Returns the number of elements that could be allocated.
//!Never throws
size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
- { return size_type(-1)/sizeof(T); }
+ { return size_type(-1)/(2u*sizeof(T)); }
//!Allocate memory for an array of count elements.
//!Throws std::bad_alloc if there is no enough memory
pointer allocate(size_type count, const void * = 0)
{
- if(BOOST_UNLIKELY(count > this->max_size()))
+ if(BOOST_UNLIKELY(count > size_type(-1)/(2u*sizeof(T))))
boost::container::throw_bad_alloc();
if(Version == 1 && count == 1){
diff --git a/boost/container/allocator.hpp b/boost/container/allocator.hpp
index aef620ce59..a14c59ebe5 100644
--- a/boost/container/allocator.hpp
+++ b/boost/container/allocator.hpp
@@ -180,7 +180,7 @@ class allocator
pointer allocate(size_type count, const void * hint= 0)
{
(void)hint;
- if(count > this->max_size())
+ if(count > size_type(-1)/(2u*sizeof(T)))
boost::container::throw_bad_alloc();
void *ret = dlmalloc_malloc(count*sizeof(T));
if(!ret)
@@ -196,7 +196,7 @@ class allocator
//!Returns the maximum number of elements that could be allocated.
//!Never throws
BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
- { return size_type(-1)/sizeof(T); }
+ { return size_type(-1)/(2u*sizeof(T)); }
//!Swaps two allocators, does nothing
//!because this allocator is stateless
diff --git a/boost/container/allocator_traits.hpp b/boost/container/allocator_traits.hpp
index 8cfb0378bc..72d90d1b43 100644
--- a/boost/container/allocator_traits.hpp
+++ b/boost/container/allocator_traits.hpp
@@ -77,7 +77,7 @@ namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-template<class T, class VoidAllocator>
+template<class T, class VoidAllocator, class Options>
class small_vector_allocator;
namespace allocator_traits_detail {
@@ -99,8 +99,8 @@ template<class T>
struct is_std_allocator< std::allocator<T> >
{ static const bool value = true; };
-template<class T>
-struct is_std_allocator< small_vector_allocator<T, std::allocator<T> > >
+template<class T, class Options>
+struct is_std_allocator< small_vector_allocator<T, std::allocator<T>, Options > >
{ static const bool value = true; };
template<class Allocator>
diff --git a/boost/container/container_fwd.hpp b/boost/container/container_fwd.hpp
index b7591cd256..2cfb20a540 100644
--- a/boost/container/container_fwd.hpp
+++ b/boost/container/container_fwd.hpp
@@ -24,6 +24,7 @@
//! - boost::container::vector
//! - boost::container::stable_vector
//! - boost::container::static_vector
+//! - boost::container::small_vector_base
//! - boost::container::small_vector
//! - boost::container::slist
//! - boost::container::list
@@ -105,15 +106,25 @@ template <class T
,class Allocator = void >
class stable_vector;
-template <class T, std::size_t Capacity>
+template < class T
+ , std::size_t Capacity
+ , class Options = void>
class static_vector;
-template < class T, std::size_t N
- , class Allocator = void >
+template < class T
+ , class Allocator = void
+ , class Options = void >
+class small_vector_base;
+
+template < class T
+ , std::size_t N
+ , class Allocator = void
+ , class Options = void >
class small_vector;
template <class T
- ,class Allocator = void >
+ ,class Allocator = void
+ ,class Options = void>
class deque;
template <class T
diff --git a/boost/container/deque.hpp b/boost/container/deque.hpp
index 1fa3e5d5d4..ae911066a3 100644
--- a/boost/container/deque.hpp
+++ b/boost/container/deque.hpp
@@ -25,6 +25,7 @@
#include <boost/container/container_fwd.hpp>
#include <boost/container/new_allocator.hpp> //new_allocator
#include <boost/container/throw_exception.hpp>
+#include <boost/container/options.hpp>
// container/detail
#include <boost/container/detail/advanced_insert_int.hpp>
#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
@@ -61,7 +62,7 @@ namespace boost {
namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class Allocator>
+template <class T, class Allocator, class Options>
class deque;
template <class T>
@@ -72,14 +73,12 @@ struct deque_value_traits
static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move<value_type>::value;
};
-// Note: this function is simply a kludge to work around several compilers'
-// bugs in handling constant expressions.
-template<class T>
-struct deque_buf_size
+template<class T, std::size_t BlockBytes, std::size_t BlockSize>
+struct deque_block_size
{
- static const std::size_t min_size = 512u;
- static const std::size_t sizeof_t = sizeof(T);
- static const std::size_t value = sizeof_t < min_size ? (min_size/sizeof_t) : std::size_t(1);
+ BOOST_STATIC_ASSERT_MSG(!(BlockBytes && BlockSize), "BlockBytes and BlockSize can't be specified at the same time");
+ static const std::size_t block_bytes = BlockBytes ? BlockBytes : 512u;
+ static const std::size_t value = BlockSize ? BlockSize : (sizeof(T) < block_bytes ? (block_bytes/sizeof(T)) : std::size_t(1));
};
namespace dtl {
@@ -132,9 +131,6 @@ class deque_iterator
, deque_iterator<Pointer, false>
, nat>::type nonconst_iterator;
- BOOST_CONTAINER_FORCEINLINE static std::size_t s_buffer_size()
- { return deque_buf_size<value_type>::value; }
-
typedef Pointer val_alloc_ptr;
typedef typename boost::intrusive::pointer_traits<Pointer>::
template rebind_pointer<Pointer>::type index_pointer;
@@ -151,8 +147,8 @@ class deque_iterator
BOOST_CONTAINER_FORCEINLINE Pointer get_last() const { return m_last; }
BOOST_CONTAINER_FORCEINLINE index_pointer get_node() const { return m_node; }
- BOOST_CONTAINER_FORCEINLINE deque_iterator(val_alloc_ptr x, index_pointer y) BOOST_NOEXCEPT_OR_NOTHROW
- : m_cur(x), m_first(*y), m_last(*y + s_buffer_size()), m_node(y)
+ BOOST_CONTAINER_FORCEINLINE deque_iterator(val_alloc_ptr x, index_pointer y, difference_type block_size) BOOST_NOEXCEPT_OR_NOTHROW
+ : m_cur(x), m_first(*y), m_last(*y + block_size), m_node(y)
{}
BOOST_CONTAINER_FORCEINLINE deque_iterator() BOOST_NOEXCEPT_OR_NOTHROW
@@ -167,7 +163,7 @@ class deque_iterator
: m_cur(x.get_cur()), m_first(x.get_first()), m_last(x.get_last()), m_node(x.get_node())
{}
- deque_iterator(Pointer cur, Pointer first, Pointer last, index_pointer node) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE deque_iterator(Pointer cur, Pointer first, Pointer last, index_pointer node) BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(cur), m_first(first), m_last(last), m_node(node)
{}
@@ -190,15 +186,20 @@ class deque_iterator
if(!this->m_cur && !x.m_cur){
return 0;
}
- return difference_type(this->s_buffer_size()) * (this->m_node - x.m_node - 1) +
+ const difference_type block_size = this->m_last - this->m_first;
+ BOOST_ASSERT(block_size);
+ return block_size * (this->m_node - x.m_node - 1) +
(this->m_cur - this->m_first) + (x.m_last - x.m_cur);
}
deque_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
{
+ BOOST_ASSERT(!!m_cur);
++this->m_cur;
if (this->m_cur == this->m_last) {
- this->priv_set_node(this->m_node + 1);
+ const difference_type block_size = m_last - m_first;
+ BOOST_ASSERT(block_size);
+ this->priv_set_node(this->m_node + 1, block_size);
this->m_cur = this->m_first;
}
return *this;
@@ -213,8 +214,11 @@ class deque_iterator
deque_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
{
+ BOOST_ASSERT(!!m_cur);
if (this->m_cur == this->m_first) {
- this->priv_set_node(this->m_node - 1);
+ const difference_type block_size = m_last - m_first;
+ BOOST_ASSERT(block_size);
+ this->priv_set_node(this->m_node - 1, block_size);
this->m_cur = this->m_last;
}
--this->m_cur;
@@ -230,16 +234,19 @@ class deque_iterator
deque_iterator& operator+=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW
{
+ BOOST_ASSERT(!!m_cur);
difference_type offset = n + (this->m_cur - this->m_first);
- if (offset >= 0 && offset < difference_type(this->s_buffer_size()))
+ const difference_type block_size = this->m_last - this->m_first;
+ BOOST_ASSERT(block_size);
+ if (offset >= 0 && offset < block_size)
this->m_cur += n;
else {
difference_type node_offset =
- offset > 0 ? offset / difference_type(this->s_buffer_size())
- : -difference_type((-offset - 1) / this->s_buffer_size()) - 1;
- this->priv_set_node(this->m_node + node_offset);
+ offset > 0 ? (offset / block_size)
+ : (-difference_type((-offset - 1) / block_size) - 1);
+ this->priv_set_node(this->m_node + node_offset, block_size);
this->m_cur = this->m_first +
- (offset - node_offset * difference_type(this->s_buffer_size()));
+ (offset - node_offset * block_size);
}
return *this;
}
@@ -274,11 +281,11 @@ class deque_iterator
BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return !(l < r); }
- BOOST_CONTAINER_FORCEINLINE void priv_set_node(index_pointer new_node) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE void priv_set_node(index_pointer new_node, difference_type block_size) BOOST_NOEXCEPT_OR_NOTHROW
{
this->m_node = new_node;
this->m_first = *new_node;
- this->m_last = this->m_first + this->s_buffer_size();
+ this->m_last = this->m_first + block_size;
}
BOOST_CONTAINER_FORCEINLINE friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_NOEXCEPT_OR_NOTHROW
@@ -287,10 +294,22 @@ class deque_iterator
} //namespace dtl {
+template<class Options>
+struct get_deque_opt
+{
+ typedef Options type;
+};
+
+template<>
+struct get_deque_opt<void>
+{
+ typedef deque_null_opt type;
+};
+
// Deque base class. It has two purposes. First, its constructor
// and destructor allocate (but don't initialize) storage. This makes
// exception safety easier.
-template <class Allocator>
+template <class Allocator, class Options>
class deque_base
{
BOOST_COPYABLE_AND_MOVABLE(deque_base)
@@ -315,19 +334,24 @@ class deque_base
typedef allocator_type stored_allocator_type;
typedef val_alloc_size size_type;
+ private:
+ typedef typename get_deque_opt<Options>::type options_type;
+
protected:
+ typedef dtl::deque_iterator<val_alloc_ptr, false> iterator;
+ typedef dtl::deque_iterator<val_alloc_ptr, true > const_iterator;
+
+ BOOST_CONSTEXPR BOOST_CONTAINER_FORCEINLINE static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW
+ { return deque_block_size<val_alloc_val, options_type::block_bytes, options_type::block_size>::value; }
typedef deque_value_traits<val_alloc_val> traits_t;
typedef ptr_alloc_t map_allocator_type;
- BOOST_CONTAINER_FORCEINLINE static size_type s_buffer_size() BOOST_NOEXCEPT_OR_NOTHROW
- { return deque_buf_size<val_alloc_val>::value; }
-
BOOST_CONTAINER_FORCEINLINE val_alloc_ptr priv_allocate_node()
- { return this->alloc().allocate(s_buffer_size()); }
+ { return this->alloc().allocate(get_block_size()); }
BOOST_CONTAINER_FORCEINLINE void priv_deallocate_node(val_alloc_ptr p) BOOST_NOEXCEPT_OR_NOTHROW
- { this->alloc().deallocate(p, s_buffer_size()); }
+ { this->alloc().deallocate(p, get_block_size()); }
BOOST_CONTAINER_FORCEINLINE ptr_alloc_ptr priv_allocate_map(size_type n)
{ return this->ptr_alloc().allocate(n); }
@@ -335,9 +359,6 @@ class deque_base
BOOST_CONTAINER_FORCEINLINE void priv_deallocate_map(ptr_alloc_ptr p, size_type n) BOOST_NOEXCEPT_OR_NOTHROW
{ this->ptr_alloc().deallocate(p, n); }
- typedef dtl::deque_iterator<val_alloc_ptr, false> iterator;
- typedef dtl::deque_iterator<val_alloc_ptr, true > const_iterator;
-
BOOST_CONTAINER_FORCEINLINE deque_base(size_type num_elements, const allocator_type& a)
: members_(a)
{ this->priv_initialize_map(num_elements); }
@@ -379,7 +400,7 @@ class deque_base
void priv_initialize_map(size_type num_elements)
{
// if(num_elements){
- size_type num_nodes = num_elements / s_buffer_size() + 1;
+ size_type num_nodes = num_elements / get_block_size() + 1;
this->members_.m_map_size = dtl::max_value((size_type) InitialMapSize, num_nodes + 2);
this->members_.m_map = this->priv_allocate_map(this->members_.m_map_size);
@@ -398,11 +419,11 @@ class deque_base
}
BOOST_CATCH_END
- this->members_.m_start.priv_set_node(nstart);
- this->members_.m_finish.priv_set_node(nfinish - 1);
+ this->members_.m_start.priv_set_node(nstart, get_block_size());
+ this->members_.m_finish.priv_set_node(nfinish - 1, get_block_size());
this->members_.m_start.m_cur = this->members_.m_start.m_first;
this->members_.m_finish.m_cur = this->members_.m_finish.m_first +
- num_elements % s_buffer_size();
+ num_elements % get_block_size();
// }
}
@@ -490,16 +511,18 @@ class deque_base
//! and removal of elements at the end of the sequence, and linear time insertion and removal of elements in the middle.
//!
//! \tparam T The type of object that is stored in the deque
-//! \tparam Allocator The allocator used for all internal memory management
-template <class T, class Allocator = new_allocator<T> >
+//! \tparam A The allocator used for all internal memory management, use void
+//! for the default allocator
+//! \tparam Options A type produced from \c boost::container::deque_options.
+template <class T, class Allocator = void, class Options = void>
#else
-template <class T, class Allocator>
+template <class T, class Allocator, class Options>
#endif
-class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
+class deque : protected deque_base<typename real_allocator<T, Allocator>::type, Options>
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
- typedef deque_base<typename real_allocator<T, Allocator>::type> Base;
+ typedef deque_base<typename real_allocator<T, Allocator>::type, Options> Base;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef typename real_allocator<T, Allocator>::type ValAllocator;
@@ -530,13 +553,15 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
private: // Internal typedefs
BOOST_COPYABLE_AND_MOVABLE(deque)
typedef typename Base::ptr_alloc_ptr index_pointer;
- BOOST_CONTAINER_FORCEINLINE static size_type s_buffer_size()
- { return Base::s_buffer_size(); }
typedef allocator_traits<ValAllocator> allocator_traits_type;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
+
+ BOOST_CONSTEXPR BOOST_CONTAINER_FORCEINLINE static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW
+ { return Base::get_block_size(); }
+
//////////////////////////////////////////////
//
// construct/copy/destroy
@@ -786,7 +811,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
//! <b>Complexity</b>: Linear to the number of elements in x.
deque& operator= (BOOST_COPY_ASSIGN_REF(deque) x)
{
- if (&x != this){
+ if (BOOST_LIKELY(&x != this)){
allocator_type &this_alloc = this->alloc();
const allocator_type &x_alloc = x.alloc();
dtl::bool_<allocator_traits_type::
@@ -814,28 +839,29 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value)
{
- BOOST_ASSERT(this != &x);
- allocator_type &this_alloc = this->alloc();
- allocator_type &x_alloc = x.alloc();
- const bool propagate_alloc = allocator_traits_type::
- propagate_on_container_move_assignment::value;
- dtl::bool_<propagate_alloc> flag;
- const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
- //Resources can be transferred if both allocators are
- //going to be equal after this function (either propagated or already equal)
- if(propagate_alloc || allocators_equal){
- //Destroy objects but retain memory in case x reuses it in the future
- this->clear();
- //Move allocator if needed
- dtl::move_alloc(this_alloc, x_alloc, flag);
- dtl::move_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
- //Nothrow swap
- this->swap_members(x);
- }
- //Else do a one by one move
- else{
- this->assign( boost::make_move_iterator(x.begin())
- , boost::make_move_iterator(x.end()));
+ if (BOOST_LIKELY(this != &x)) {
+ allocator_type &this_alloc = this->alloc();
+ allocator_type &x_alloc = x.alloc();
+ const bool propagate_alloc = allocator_traits_type::
+ propagate_on_container_move_assignment::value;
+ dtl::bool_<propagate_alloc> flag;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ //Destroy objects but retain memory in case x reuses it in the future
+ this->clear();
+ //Move allocator if needed
+ dtl::move_alloc(this_alloc, x_alloc, flag);
+ dtl::move_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
+ //Nothrow swap
+ this->swap_members(x);
+ }
+ //Else do a one by one move
+ else{
+ this->assign( boost::make_move_iterator(x.begin())
+ , boost::make_move_iterator(x.end()));
+ }
}
return *this;
}
@@ -1776,7 +1802,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
for (index_pointer node = this->members_.m_start.m_node + 1;
node < this->members_.m_finish.m_node;
++node) {
- this->priv_destroy_range(*node, *node + this->s_buffer_size());
+ this->priv_destroy_range(*node, *node + get_block_size());
this->priv_deallocate_node(*node);
}
@@ -2087,13 +2113,13 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
BOOST_TRY {
for ( ; cur < this->members_.m_finish.m_node; ++cur){
boost::container::uninitialized_fill_alloc
- (this->alloc(), *cur, *cur + this->s_buffer_size(), value);
+ (this->alloc(), *cur, *cur + get_block_size(), value);
}
boost::container::uninitialized_fill_alloc
(this->alloc(), this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value);
}
BOOST_CATCH(...){
- this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur));
+ this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur, get_block_size()));
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -2125,14 +2151,14 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
BOOST_TRY {
for (; cur_node < this->members_.m_finish.m_node; ++cur_node) {
FwdIt mid = first;
- boost::container::iterator_advance(mid, this->s_buffer_size());
+ boost::container::iterator_advance(mid, get_block_size());
::boost::container::uninitialized_copy_alloc(this->alloc(), first, mid, *cur_node);
first = mid;
}
::boost::container::uninitialized_copy_alloc(this->alloc(), first, last, this->members_.m_finish.m_first);
}
BOOST_CATCH(...){
- this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node));
+ this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node, get_block_size()));
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -2142,7 +2168,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
void priv_pop_back_aux() BOOST_NOEXCEPT_OR_NOTHROW
{
this->priv_deallocate_node(this->members_.m_finish.m_first);
- this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1);
+ this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1, get_block_size());
this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1;
allocator_traits_type::destroy
( this->alloc()
@@ -2161,7 +2187,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
, boost::movelib::to_raw_pointer(this->members_.m_start.m_cur)
);
this->priv_deallocate_node(this->members_.m_start.m_first);
- this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1);
+ this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1, get_block_size());
this->members_.m_start.m_cur = this->members_.m_start.m_first;
}
@@ -2170,8 +2196,8 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
size_type vacancies = this->members_.m_start.m_cur - this->members_.m_start.m_first;
if (n > vacancies){
size_type new_elems = n-vacancies;
- size_type new_nodes = (new_elems + this->s_buffer_size() - 1) /
- this->s_buffer_size();
+ size_type new_nodes = (new_elems + get_block_size() - 1) /
+ get_block_size();
size_type s = (size_type)(this->members_.m_start.m_node - this->members_.m_map);
if (new_nodes > s){
this->priv_reallocate_map(new_nodes, true);
@@ -2196,7 +2222,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
size_type vacancies = (this->members_.m_finish.m_last - this->members_.m_finish.m_cur) - 1;
if (n > vacancies){
size_type new_elems = n - vacancies;
- size_type new_nodes = (new_elems + this->s_buffer_size() - 1)/s_buffer_size();
+ size_type new_nodes = (new_elems + get_block_size() - 1)/get_block_size();
size_type s = (size_type)(this->members_.m_map_size - (this->members_.m_finish.m_node - this->members_.m_map));
if (new_nodes + 1 > s){
this->priv_reallocate_map(new_nodes, false);
@@ -2245,8 +2271,8 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type>
this->members_.m_map_size = new_map_size;
}
- this->members_.m_start.priv_set_node(new_nstart);
- this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1);
+ this->members_.m_start.priv_set_node(new_nstart, get_block_size());
+ this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1, get_block_size());
}
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
@@ -2266,11 +2292,12 @@ namespace boost {
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class T, class Allocator>
-struct has_trivial_destructor_after_move<boost::container::deque<T, Allocator> >
+template <class T, class Allocator, class Options>
+struct has_trivial_destructor_after_move<boost::container::deque<T, Allocator, Options> >
{
- typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ typedef typename boost::container::deque<T, Allocator, Options>::allocator_type allocator_type;
+ typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value;
};
diff --git a/boost/container/detail/advanced_insert_int.hpp b/boost/container/detail/advanced_insert_int.hpp
index 17ceb013fd..28e7ae953f 100644
--- a/boost/container/detail/advanced_insert_int.hpp
+++ b/boost/container/detail/advanced_insert_int.hpp
@@ -128,7 +128,7 @@ struct insert_value_initialized_n_proxy
void copy_n_and_update(Allocator &a, Iterator p, size_type n) const
{
for (; 0 < n; --n, ++p){
- typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
value_type *vp = reinterpret_cast<value_type *>(v.data);
alloc_traits::construct(a, vp);
value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
@@ -151,7 +151,7 @@ struct insert_default_initialized_n_proxy
{
if(!is_pod<value_type>::value){
for (; 0 < n; --n, ++p){
- typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
value_type *vp = reinterpret_cast<value_type *>(v.data);
alloc_traits::construct(a, vp, default_init);
value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
@@ -195,17 +195,17 @@ struct insert_move_proxy
typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_type;
- explicit insert_move_proxy(value_type &v)
+ BOOST_CONTAINER_FORCEINLINE explicit insert_move_proxy(value_type &v)
: v_(v)
{}
- void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
+ BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
}
- void copy_n_and_update(Allocator &, Iterator p, size_type n) const
+ BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
*p = ::boost::move(v_);
@@ -288,7 +288,7 @@ struct insert_emplace_proxy
void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
BOOST_ASSERT(n ==1); (void)n;
- typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
value_type *vp = reinterpret_cast<value_type *>(v.data);
alloc_traits::construct(a, vp,
::boost::forward<Args>(get<IdxPack>(this->args_))...);
@@ -398,7 +398,7 @@ struct insert_emplace_proxy_arg##N\
void copy_n_and_update(Allocator &a, Iterator p, size_type n)\
{\
BOOST_ASSERT(n == 1); (void)n;\
- typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
BOOST_ASSERT((((size_type)(&v)) % alignment_of<value_type>::value) == 0);\
value_type *vp = reinterpret_cast<value_type *>(v.data);\
alloc_traits::construct(a, vp BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
diff --git a/boost/container/detail/container_rebind.hpp b/boost/container/detail/container_rebind.hpp
index 0ebb4789e4..0af9b9e9f4 100644
--- a/boost/container/detail/container_rebind.hpp
+++ b/boost/container/detail/container_rebind.hpp
@@ -19,6 +19,7 @@
#endif
#include <boost/container/allocator_traits.hpp>
+#include <boost/container/container_fwd.hpp>
namespace boost {
@@ -33,14 +34,14 @@ namespace dtl {
template <template <class, class, class...> class Cont, typename V, typename A, class... An, class U>
struct container_rebind<Cont<V, A, An...>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, An...> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, An...> type;
};
//Needed for non-conforming compilers like GCC 4.3
template <template <class, class> class Cont, typename V, typename A, class U>
struct container_rebind<Cont<V, A>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type> type;
};
template <template <class> class Cont, typename V, class U>
@@ -49,27 +50,6 @@ namespace dtl {
typedef Cont<U> type;
};
- //for small_vector,static_vector
-
- template <template <class, std::size_t, class, class...> class Cont, typename V, std::size_t N, typename A, class... An, class U>
- struct container_rebind<Cont<V, N, A, An...>, U>
- {
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, An...> type;
- };
-
- //Needed for non-conforming compilers like GCC 4.3
- template <template <class, std::size_t, class> class Cont, typename V, std::size_t N, typename A, class U>
- struct container_rebind<Cont<V, N, A>, U>
- {
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
- };
-
- template <template <class, std::size_t> class Cont, typename V, std::size_t N, class U>
- struct container_rebind<Cont<V, N>, U>
- {
- typedef Cont<U, N> type;
- };
-
#else //C++03 compilers
template <template <class> class Cont //0arg
@@ -85,7 +65,7 @@ namespace dtl {
, class U>
struct container_rebind<Cont<V, A>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type> type;
};
template <template <class, class, class> class Cont //1arg
@@ -93,7 +73,7 @@ namespace dtl {
, class U>
struct container_rebind<Cont<V, A, P0>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0> type;
};
template <template <class, class, class, class> class Cont //2arg
@@ -101,7 +81,7 @@ namespace dtl {
, class U>
struct container_rebind<Cont<V, A, P0, P1>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1> type;
};
template <template <class, class, class, class, class> class Cont //3arg
@@ -109,7 +89,7 @@ namespace dtl {
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2> type;
};
template <template <class, class, class, class, class, class> class Cont //4arg
@@ -117,7 +97,7 @@ namespace dtl {
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3> type;
};
template <template <class, class, class, class, class, class, class> class Cont //5arg
@@ -125,7 +105,7 @@ namespace dtl {
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4> type;
};
template <template <class, class, class, class, class, class, class, class> class Cont //6arg
@@ -133,7 +113,7 @@ namespace dtl {
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5> type;
};
template <template <class, class, class, class, class, class, class, class, class> class Cont //7arg
@@ -141,7 +121,7 @@ namespace dtl {
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6> type;
};
template <template <class, class, class, class, class, class, class, class, class, class> class Cont //8arg
@@ -149,7 +129,7 @@ namespace dtl {
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6, P7>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7> type;
};
template <template <class, class, class, class, class, class, class, class, class, class, class> class Cont //9arg
@@ -157,100 +137,25 @@ namespace dtl {
, class U>
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6, P7, P8>, U>
{
- typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7, P8> type;
- };
-
- //For small_vector/static_vector
- template <template <class, std::size_t> class Cont //0arg
- , typename V, std::size_t N
- , class U>
- struct container_rebind<Cont<V, N>, U>
- {
- typedef Cont<U, N> type;
- };
-
- template <template <class, std::size_t, class> class Cont //0arg
- , typename V, std::size_t N, typename A
- , class U>
- struct container_rebind<Cont<V, N, A>, U>
- {
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
- };
-
- template <template <class, std::size_t, class, class> class Cont //1arg
- , typename V, std::size_t N, typename A, class P0
- , class U>
- struct container_rebind<Cont<V, N, A, P0>, U>
- {
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0> type;
- };
-
- template <template <class, std::size_t, class, class, class> class Cont //2arg
- , typename V, std::size_t N, typename A, class P0, class P1
- , class U>
- struct container_rebind<Cont<V, N, A, P0, P1>, U>
- {
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1> type;
- };
-
- template <template <class, std::size_t, class, class, class, class> class Cont //3arg
- , typename V, std::size_t N, typename A, class P0, class P1, class P2
- , class U>
- struct container_rebind<Cont<V, N, A, P0, P1, P2>, U>
- {
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2> type;
- };
-
- template <template <class, std::size_t, class, class, class, class, class> class Cont //4arg
- , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3
- , class U>
- struct container_rebind<Cont<V, N, A, P0, P1, P2, P3>, U>
- {
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3> type;
- };
-
- template <template <class, std::size_t, class, class, class, class, class, class> class Cont //5arg
- , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4
- , class U>
- struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4>, U>
- {
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4> type;
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7, P8> type;
};
- template <template <class, std::size_t, class, class, class, class, class, class, class> class Cont //6arg
- , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5
- , class U>
- struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5>, U>
- {
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5> type;
- };
+#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template <template <class, std::size_t, class, class, class, class, class, class, class, class> class Cont //7arg
- , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6
- , class U>
- struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6>, U>
- {
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6> type;
- };
+ //for small_vector,static_vector
- template <template <class, std::size_t, class, class, class, class, class, class, class, class, class> class Cont //8arg
- , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7
- , class U>
- struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6, P7>, U>
+ template <typename V, std::size_t N, typename A, class U>
+ struct container_rebind<small_vector<V, N, A>, U>
{
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7> type;
+ typedef small_vector<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type> type;
};
- template <template <class, std::size_t, class, class, class, class, class, class, class, class, class, class> class Cont //9arg
- , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8
- , class U>
- struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6, P7, P8>, U>
+ template <typename V, std::size_t N, typename O, class U>
+ struct container_rebind<static_vector<V, N, O>, U>
{
- typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7, P8> type;
+ typedef static_vector<U, N, O> type;
};
-#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-
} //namespace dtl {
} //namespace container {
} //namespace boost {
diff --git a/boost/container/detail/copy_move_algo.hpp b/boost/container/detail/copy_move_algo.hpp
index 29d47ccbda..b71560d9e5 100644
--- a/boost/container/detail/copy_move_algo.hpp
+++ b/boost/container/detail/copy_move_algo.hpp
@@ -177,8 +177,7 @@ inline F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
value_type *const dest_raw = boost::movelib::iterator_to_raw_pointer(r);
const value_type *const beg_raw = boost::movelib::iterator_to_raw_pointer(f);
const value_type *const end_raw = boost::movelib::iterator_to_raw_pointer(l);
- if(BOOST_LIKELY(beg_raw != end_raw)){
- BOOST_ASSERT(beg_raw != 0);
+ if(BOOST_LIKELY(beg_raw != end_raw && dest_raw && beg_raw)){
const typename boost::container::iterator_traits<I>::difference_type n = end_raw - beg_raw;
std::memmove(dest_raw, beg_raw, sizeof(value_type)*n);
boost::container::iterator_advance(r, n);
@@ -522,9 +521,9 @@ inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, I>::type
{
F back = r;
BOOST_TRY{
- while (n--) {
+ while (n) {
boost::container::construct_in_place(a, boost::movelib::iterator_to_raw_pointer(r), f);
- ++f; ++r;
+ ++f; ++r; --n;
}
}
BOOST_CATCH(...){
diff --git a/boost/container/detail/flat_tree.hpp b/boost/container/detail/flat_tree.hpp
index 476a63aca0..c346360b46 100644
--- a/boost/container/detail/flat_tree.hpp
+++ b/boost/container/detail/flat_tree.hpp
@@ -205,7 +205,7 @@ BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique //has_merge_unique == f
size_type const old_sz = dest.size();
iterator const first_new = dest.insert(dest.cend(), first, last );
- iterator e = boost::movelib::inplace_set_difference(first_new, dest.end(), dest.begin(), first_new, comp);
+ iterator e = boost::movelib::inplace_set_unique_difference(first_new, dest.end(), dest.begin(), first_new, comp);
dest.erase(e, dest.end());
dtl::bool_<is_contiguous_container<SequenceContainer>::value> contiguous_tag;
(flat_tree_container_inplace_merge)(dest, dest.begin()+old_sz, comp, contiguous_tag);
@@ -883,10 +883,14 @@ class flat_tree
//Step 3: only left unique values from the back not already present in the original range
typename container_type::iterator const e = boost::movelib::inplace_set_unique_difference
(it, seq.end(), seq.begin(), it, val_cmp);
- seq.erase(e, seq.cend());
- //Step 4: merge both ranges
- (flat_tree_container_inplace_merge)(seq, it, this->priv_value_comp(), contiguous_tag);
+ seq.erase(e, seq.cend());
+ //it might be invalidated by erasing [e, seq.end) if e == it
+ if (it != e)
+ {
+ //Step 4: merge both ranges
+ (flat_tree_container_inplace_merge)(seq, it, this->priv_value_comp(), contiguous_tag);
+ }
}
template <class InIt>
@@ -922,7 +926,7 @@ class flat_tree
template <class... Args>
std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args)
{
- typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
value_type *pval = reinterpret_cast<value_type *>(v.data);
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
stored_allocator_traits::construct(a, pval, ::boost::forward<Args>(args)... );
@@ -934,7 +938,7 @@ class flat_tree
iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
//hint checked in insert_unique
- typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
value_type *pval = reinterpret_cast<value_type *>(v.data);
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
stored_allocator_traits::construct(a, pval, ::boost::forward<Args>(args)... );
@@ -945,7 +949,7 @@ class flat_tree
template <class... Args>
iterator emplace_equal(BOOST_FWD_REF(Args)... args)
{
- typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
value_type *pval = reinterpret_cast<value_type *>(v.data);
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
stored_allocator_traits::construct(a, pval, ::boost::forward<Args>(args)... );
@@ -957,7 +961,7 @@ class flat_tree
iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
//hint checked in insert_equal
- typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
value_type *pval = reinterpret_cast<value_type *>(v.data);
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
stored_allocator_traits::construct(a, pval, ::boost::forward<Args>(args)... );
@@ -994,7 +998,7 @@ class flat_tree
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
std::pair<iterator, bool> emplace_unique(BOOST_MOVE_UREF##N)\
{\
- typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
value_type *pval = reinterpret_cast<value_type *>(v.data);\
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
stored_allocator_traits::construct(a, pval BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
@@ -1005,7 +1009,7 @@ class flat_tree
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
- typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
value_type *pval = reinterpret_cast<value_type *>(v.data);\
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
stored_allocator_traits::construct(a, pval BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
@@ -1016,7 +1020,7 @@ class flat_tree
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
iterator emplace_equal(BOOST_MOVE_UREF##N)\
{\
- typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
value_type *pval = reinterpret_cast<value_type *>(v.data);\
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
stored_allocator_traits::construct(a, pval BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
@@ -1027,7 +1031,7 @@ class flat_tree
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
iterator emplace_hint_equal(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
- typename aligned_storage <sizeof(value_type), alignment_of<value_type>::value>::type v;\
+ typename dtl::aligned_storage <sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
value_type *pval = reinterpret_cast<value_type *>(v.data);\
get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
stored_allocator_traits::construct(a, pval BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
@@ -1601,7 +1605,7 @@ class flat_tree
const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb);
- if(lb != last && static_cast<difference_type>(!key_cmp(k, key_extract(*lb)))){
+ if(lb != last && !key_cmp(k, key_extract(*lb))){
++ub;
}
return std::pair<RanIt, RanIt>(lb, ub);
@@ -1618,11 +1622,11 @@ template <class T, class KeyOfValue,
class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::dtl::flat_tree<T, KeyOfValue, Compare, AllocatorOrContainer> >
{
- typedef typename boost::container::dtl::select_container_type<T, AllocatorOrContainer>::type container_type;
- typedef typename container_type::allocator_type allocator_t;
- typedef typename ::boost::container::allocator_traits<allocator_t>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<allocator_t>::value &&
- ::boost::has_trivial_destructor_after_move<pointer>::value;
+ typedef boost::container::dtl::flat_tree<T, KeyOfValue, Compare, AllocatorOrContainer> flat_tree;
+ typedef typename flat_tree::container_type container_type;
+ typedef typename flat_tree::key_compare key_compare;
+ static const bool value = ::boost::has_trivial_destructor_after_move<container_type>::value &&
+ ::boost::has_trivial_destructor_after_move<key_compare>::value;
};
} //namespace boost {
diff --git a/boost/container/detail/mpl.hpp b/boost/container/detail/mpl.hpp
index 4706c58022..ffae180c85 100644
--- a/boost/container/detail/mpl.hpp
+++ b/boost/container/detail/mpl.hpp
@@ -69,11 +69,11 @@ struct select1st
typedef FirstType type;
template<class T>
- const type& operator()(const T& x) const
+ BOOST_CONTAINER_FORCEINLINE const type& operator()(const T& x) const
{ return x.first; }
template<class T>
- type& operator()(T& x)
+ BOOST_CONTAINER_FORCEINLINE type& operator()(T& x)
{ return const_cast<type&>(x.first); }
};
diff --git a/boost/container/detail/thread_mutex.hpp b/boost/container/detail/thread_mutex.hpp
index 66d64b9c5e..4027ff2e01 100644
--- a/boost/container/detail/thread_mutex.hpp
+++ b/boost/container/detail/thread_mutex.hpp
@@ -142,25 +142,25 @@ class thread_mutex
thread_mutex()
{
#ifdef BOOST_PLAT_WINDOWS_UWP
- InitializeCriticalSectionEx(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect), 4000, 0);
+ (InitializeCriticalSectionEx)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect), 4000, 0);
#else
- InitializeCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
+ (InitializeCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
#endif
}
void lock()
{
- EnterCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
+ (EnterCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
}
void unlock()
{
- LeaveCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
+ (LeaveCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
}
~thread_mutex()
{
- DeleteCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
+ (DeleteCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
}
private:
diff --git a/boost/container/detail/tree.hpp b/boost/container/detail/tree.hpp
index 08965e5a6d..23fbfded5d 100644
--- a/boost/container/detail/tree.hpp
+++ b/boost/container/detail/tree.hpp
@@ -788,7 +788,7 @@ class tree
tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x)
{
- if (&x != this){
+ if (BOOST_LIKELY(this != &x)) {
NodeAlloc &this_alloc = this->get_stored_allocator();
const NodeAlloc &x_alloc = x.get_stored_allocator();
dtl::bool_<allocator_traits<NodeAlloc>::
@@ -822,39 +822,40 @@ class tree
allocator_traits_type::is_always_equal::value) &&
boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
{
- BOOST_ASSERT(this != &x);
- NodeAlloc &this_alloc = this->node_alloc();
- NodeAlloc &x_alloc = x.node_alloc();
- const bool propagate_alloc = allocator_traits<NodeAlloc>::
- propagate_on_container_move_assignment::value;
- const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
- //Resources can be transferred if both allocators are
- //going to be equal after this function (either propagated or already equal)
- if(propagate_alloc || allocators_equal){
- //Destroy
- this->clear();
- //Move allocator if needed
- this->AllocHolder::move_assign_alloc(x);
- //Obtain resources
- this->icont() = boost::move(x.icont());
- }
- //Else do a one by one move
- else{
- //Transfer all the nodes to a temporary tree
- //If anything goes wrong, all the nodes will be destroyed
- //automatically
- Icont other_tree(::boost::move(this->icont()));
-
- //Now recreate the source tree reusing nodes stored by other_tree
- this->icont().clone_from
- (::boost::move(x.icont())
- , RecyclingCloner<AllocHolder, true>(*this, other_tree)
- , Destroyer(this->node_alloc()));
-
- //If there are remaining nodes, destroy them
- NodePtr p;
- while((p = other_tree.unlink_leftmost_without_rebalance())){
- AllocHolder::destroy_node(p);
+ if (BOOST_LIKELY(this != &x)) {
+ NodeAlloc &this_alloc = this->node_alloc();
+ NodeAlloc &x_alloc = x.node_alloc();
+ const bool propagate_alloc = allocator_traits<NodeAlloc>::
+ propagate_on_container_move_assignment::value;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ //Destroy
+ this->clear();
+ //Move allocator if needed
+ this->AllocHolder::move_assign_alloc(x);
+ //Obtain resources
+ this->icont() = boost::move(x.icont());
+ }
+ //Else do a one by one move
+ else{
+ //Transfer all the nodes to a temporary tree
+ //If anything goes wrong, all the nodes will be destroyed
+ //automatically
+ Icont other_tree(::boost::move(this->icont()));
+
+ //Now recreate the source tree reusing nodes stored by other_tree
+ this->icont().clone_from
+ (::boost::move(x.icont())
+ , RecyclingCloner<AllocHolder, true>(*this, other_tree)
+ , Destroyer(this->node_alloc()));
+
+ //If there are remaining nodes, destroy them
+ NodePtr p;
+ while((p = other_tree.unlink_leftmost_without_rebalance())){
+ AllocHolder::destroy_node(p);
+ }
}
}
return *this;
@@ -1515,8 +1516,9 @@ struct has_trivial_destructor_after_move
<T, KeyOfValue, Compare, Allocator, Options>
>
{
- typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ typedef typename ::boost::container::dtl::tree<T, KeyOfValue, Compare, Allocator, Options>::allocator_type allocator_type;
+ typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value &&
::boost::has_trivial_destructor_after_move<Compare>::value;
};
diff --git a/boost/container/detail/version_type.hpp b/boost/container/detail/version_type.hpp
index 58e9da6aae..389606a567 100644
--- a/boost/container/detail/version_type.hpp
+++ b/boost/container/detail/version_type.hpp
@@ -45,8 +45,9 @@ namespace impl{
template <class T>
struct extract_version
- : T::version
-{};
+{
+ typedef typename T::version type;
+};
template <class T>
struct has_version
@@ -69,7 +70,7 @@ struct version
template <class T>
struct version<T, true>
{
- static const unsigned value = extract_version<T>::value;
+ static const unsigned value = extract_version<T>::type::value;
};
} //namespace impl
diff --git a/boost/container/flat_map.hpp b/boost/container/flat_map.hpp
index 283ab332da..f1d5ed2fc4 100644
--- a/boost/container/flat_map.hpp
+++ b/boost/container/flat_map.hpp
@@ -788,12 +788,12 @@ class flat_map
//! Complexity: Logarithmic in the size of the container in general, but amortized constant if
//! the new element is inserted just before hint.
template <class M>
- BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(const_iterator hint, const key_type& k, BOOST_FWD_REF(M) obj)
+ BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, const key_type& k, BOOST_FWD_REF(M) obj)
{
- return dtl::force_copy< std::pair<iterator, bool> >
+ return dtl::force_copy<iterator>
(this->m_flat_tree.insert_or_assign
( dtl::force_copy<impl_const_iterator>(hint)
- , k, ::boost::forward<M>(obj))
+ , k, ::boost::forward<M>(obj)).first
);
}
@@ -812,12 +812,12 @@ class flat_map
//! Complexity: Logarithmic in the size of the container in general, but amortized constant if
//! the new element is inserted just before hint.
template <class M>
- BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
+ BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
{
- return dtl::force_copy< std::pair<iterator, bool> >
+ return dtl::force_copy<iterator>
(this->m_flat_tree.insert_or_assign
( dtl::force_copy<impl_const_iterator>(hint)
- , ::boost::move(k), ::boost::forward<M>(obj))
+ , ::boost::move(k), ::boost::forward<M>(obj)).first
);
}
@@ -1353,7 +1353,9 @@ class flat_map
//! <b>Complexity</b>: log(size())+count(k)
template<class K>
BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
- { return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end()); }
+ //Don't use find() != end optimization here as transparent comparators with key K might
+ //return a different range than key_type (which can only return a single element range)
+ { return m_flat_tree.count(x); }
//! <b>Returns</b>: Returns true if there is an element with key
//! equivalent to key in the container, otherwise false.
@@ -1465,7 +1467,9 @@ class flat_map
//! <b>Complexity</b>: Logarithmic.
template<class K>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const K& x)
- { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
+ //Don't use lower_bound_range optimization here as transparent comparators with key K might
+ //return a different range than key_type (which can only return a single element range)
+ { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
//! <b>Requires</b>: This overload is available only if
//! key_compare::is_transparent exists.
@@ -1475,7 +1479,9 @@ class flat_map
//! <b>Complexity</b>: Logarithmic.
template<class K>
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const K& x) const
- { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
+ //Don't use lower_bound_range optimization here as transparent comparators with key K might
+ //return a different range than key_type (which can only return a single element range)
+ { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
//! <b>Effects</b>: Extracts the internal sequence container.
//!
@@ -1651,10 +1657,10 @@ flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, A
template <class Key, class T, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::flat_map<Key, T, Compare, AllocatorOrContainer> >
{
- typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
- ::boost::has_trivial_destructor_after_move<pointer>::value &&
- ::boost::has_trivial_destructor_after_move<Compare>::value;
+ typedef ::boost::container::dtl::pair<Key, T> value_t;
+ typedef typename ::boost::container::dtl::container_or_allocator_rebind<AllocatorOrContainer, value_t>::type alloc_or_cont_t;
+ typedef ::boost::container::dtl::flat_tree<value_t,::boost::container::dtl::select1st<Key>, Compare, alloc_or_cont_t> tree;
+ static const bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
};
namespace container {
@@ -2961,10 +2967,10 @@ namespace boost {
template <class Key, class T, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T, Compare, AllocatorOrContainer> >
{
- typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
- ::boost::has_trivial_destructor_after_move<pointer>::value &&
- ::boost::has_trivial_destructor_after_move<Compare>::value;
+ typedef ::boost::container::dtl::pair<Key, T> value_t;
+ typedef typename ::boost::container::dtl::container_or_allocator_rebind<AllocatorOrContainer, value_t>::type alloc_or_cont_t;
+ typedef ::boost::container::dtl::flat_tree<value_t,::boost::container::dtl::select1st<Key>, Compare, alloc_or_cont_t> tree;
+ static const bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
};
} //namespace boost {
diff --git a/boost/container/flat_set.hpp b/boost/container/flat_set.hpp
index 080beb5fae..7cb1d5cf01 100644
--- a/boost/container/flat_set.hpp
+++ b/boost/container/flat_set.hpp
@@ -925,7 +925,9 @@ class flat_set
//! <b>Complexity</b>: log(size())+count(k)
template<typename K>
BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
- { return static_cast<size_type>(this->tree_t::find(x) != this->tree_t::cend()); }
+ //Don't use find() != end optimization here as transparent comparators with key K might
+ //return a different range than key_type (which can only return a single element range)
+ { return this->tree_t::count(x); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1031,7 +1033,9 @@ class flat_set
//! <b>Complexity</b>: Logarithmic
template<typename K>
std::pair<iterator,iterator> equal_range(const K& x)
- { return this->tree_t::lower_bound_range(x); }
+ //Don't use lower_bound_range optimization here as transparent comparators with key K might
+ //return a different range than key_type (which can only return a single element range)
+ { return this->tree_t::equal_range(x); }
//! <b>Requires</b>: This overload is available only if
//! key_compare::is_transparent exists.
@@ -1041,7 +1045,9 @@ class flat_set
//! <b>Complexity</b>: Logarithmic
template<typename K>
std::pair<const_iterator,const_iterator> equal_range(const K& x) const
- { return this->tree_t::lower_bound_range(x); }
+ //Don't use lower_bound_range optimization here as transparent comparators with key K might
+ //return a different range than key_type (which can only return a single element range)
+ { return this->tree_t::equal_range(x); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1192,10 +1198,8 @@ flat_set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, A
template <class Key, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::flat_set<Key, Compare, AllocatorOrContainer> >
{
- typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
- ::boost::has_trivial_destructor_after_move<pointer>::value &&
- ::boost::has_trivial_destructor_after_move<Compare>::value;
+ typedef ::boost::container::dtl::flat_tree<Key, ::boost::container::dtl::identity<Key>, Compare, AllocatorOrContainer> tree;
+ static const bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
};
namespace container {
@@ -1926,10 +1930,8 @@ flat_multiset(ordered_range_t, InputIterator, InputIterator, Compare const&, All
template <class Key, class Compare, class AllocatorOrContainer>
struct has_trivial_destructor_after_move<boost::container::flat_multiset<Key, Compare, AllocatorOrContainer> >
{
- typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
- ::boost::has_trivial_destructor_after_move<pointer>::value &&
- ::boost::has_trivial_destructor_after_move<Compare>::value;
+ typedef ::boost::container::dtl::flat_tree<Key, ::boost::container::dtl::identity<Key>, Compare, AllocatorOrContainer> tree;
+ static const bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
};
namespace container {
diff --git a/boost/container/list.hpp b/boost/container/list.hpp
index ec5a4871e1..f9ff663cf1 100644
--- a/boost/container/list.hpp
+++ b/boost/container/list.hpp
@@ -76,7 +76,7 @@ struct list_node
typedef T internal_type;
typedef typename list_hook<VoidPointer>::type hook_type;
- typedef typename aligned_storage<sizeof(T), alignment_of<T>::value>::type storage_t;
+ typedef typename dtl::aligned_storage<sizeof(T), dtl::alignment_of<T>::value>::type storage_t;
storage_t m_storage;
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000)
@@ -367,7 +367,7 @@ class list
//! <b>Complexity</b>: Linear to the number of elements in x.
list& operator=(BOOST_COPY_ASSIGN_REF(list) x)
{
- if (&x != this){
+ if (BOOST_LIKELY(this != &x)) {
NodeAlloc &this_alloc = this->node_alloc();
const NodeAlloc &x_alloc = x.node_alloc();
dtl::bool_<allocator_traits_type::
@@ -396,26 +396,27 @@ class list
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value)
{
- BOOST_ASSERT(this != &x);
- NodeAlloc &this_alloc = this->node_alloc();
- NodeAlloc &x_alloc = x.node_alloc();
- const bool propagate_alloc = allocator_traits_type::
- propagate_on_container_move_assignment::value;
- const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
- //Resources can be transferred if both allocators are
- //going to be equal after this function (either propagated or already equal)
- if(propagate_alloc || allocators_equal){
- //Destroy
- this->clear();
- //Move allocator if needed
- this->AllocHolder::move_assign_alloc(x);
- //Obtain resources
- this->icont() = boost::move(x.icont());
- }
- //Else do a one by one move
- else{
- this->assign( boost::make_move_iterator(x.begin())
- , boost::make_move_iterator(x.end()));
+ if (BOOST_LIKELY(this != &x)) {
+ NodeAlloc &this_alloc = this->node_alloc();
+ NodeAlloc &x_alloc = x.node_alloc();
+ const bool propagate_alloc = allocator_traits_type::
+ propagate_on_container_move_assignment::value;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ //Destroy
+ this->clear();
+ //Move allocator if needed
+ this->AllocHolder::move_assign_alloc(x);
+ //Obtain resources
+ this->icont() = boost::move(x.icont());
+ }
+ //Else do a one by one move
+ else{
+ this->assign( boost::make_move_iterator(x.begin())
+ , boost::make_move_iterator(x.end()));
+ }
}
return *this;
}
@@ -1521,8 +1522,9 @@ list(InputIterator, InputIterator, ValueAllocator const&) ->
template <class T, class Allocator>
struct has_trivial_destructor_after_move<boost::container::list<T, Allocator> >
{
- typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ typedef typename boost::container::list<T, Allocator>::allocator_type allocator_type;
+ typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value;
};
diff --git a/boost/container/map.hpp b/boost/container/map.hpp
index a21228b51c..447f4ad399 100644
--- a/boost/container/map.hpp
+++ b/boost/container/map.hpp
@@ -629,7 +629,7 @@ class map
//! the new element is inserted just before hint.
template <class M>
BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, const key_type& k, BOOST_FWD_REF(M) obj)
- { return this->base_t::insert_or_assign(hint, k, ::boost::forward<M>(obj)); }
+ { return this->base_t::insert_or_assign(hint, k, ::boost::forward<M>(obj)).first; }
//! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
@@ -647,7 +647,7 @@ class map
//! the new element is inserted just before hint.
template <class M>
BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
- { return this->base_t::insert_or_assign(hint, ::boost::move(k), ::boost::forward<M>(obj)); }
+ { return this->base_t::insert_or_assign(hint, ::boost::move(k), ::boost::forward<M>(obj)).first; }
//! <b>Returns</b>: A reference to the element whose key is equivalent to x.
//! Throws: An exception object of type out_of_range if no such element is present.
@@ -1366,13 +1366,11 @@ map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Alloca
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class Key, class T, class Compare, class Allocator>
-struct has_trivial_destructor_after_move<boost::container::map<Key, T, Compare, Allocator> >
+template <class Key, class T, class Compare, class Allocator, class Options>
+struct has_trivial_destructor_after_move<boost::container::map<Key, T, Compare, Allocator, Options> >
{
- typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
- ::boost::has_trivial_destructor_after_move<pointer>::value &&
- ::boost::has_trivial_destructor_after_move<Compare>::value;
+ typedef ::boost::container::dtl::tree<std::pair<const Key, T>, int, Compare, Allocator, Options> tree;
+ static const bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
};
namespace container {
@@ -2292,13 +2290,11 @@ multimap(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocato
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class Key, class T, class Compare, class Allocator>
-struct has_trivial_destructor_after_move<boost::container::multimap<Key, T, Compare, Allocator> >
+template <class Key, class T, class Compare, class Allocator, class Options>
+struct has_trivial_destructor_after_move<boost::container::multimap<Key, T, Compare, Allocator, Options> >
{
- typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
- ::boost::has_trivial_destructor_after_move<pointer>::value &&
- ::boost::has_trivial_destructor_after_move<Compare>::value;
+ typedef ::boost::container::dtl::tree<std::pair<const Key, T>, int, Compare, Allocator, Options> tree;
+ static const bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
};
namespace container {
diff --git a/boost/container/new_allocator.hpp b/boost/container/new_allocator.hpp
index 51065efa73..4801f70826 100644
--- a/boost/container/new_allocator.hpp
+++ b/boost/container/new_allocator.hpp
@@ -72,6 +72,13 @@ class new_allocator<void>
new_allocator(const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
{}
+ //!Copy assignment operator from other new_allocator.
+ //!Never throws
+ new_allocator& operator=(const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ return *this;
+ }
+
//!Constructor from related new_allocator.
//!Never throws
template<class T2>
@@ -130,6 +137,13 @@ class new_allocator
new_allocator(const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
{}
+ //!Copy assignment operator from other new_allocator.
+ //!Never throws
+ new_allocator& operator=(const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ return *this;
+ }
+
//!Constructor from related new_allocator.
//!Never throws
template<class T2>
@@ -140,7 +154,8 @@ 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()))
+ const std::size_t max_count = std::size_t(-1)/(2*sizeof(T));
+ if(BOOST_UNLIKELY(count > max_count))
throw_bad_alloc();
return static_cast<T*>(::operator new(count*sizeof(T)));
}
@@ -153,7 +168,7 @@ class new_allocator
//!Returns the maximum number of elements that could be allocated.
//!Never throws
size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
- { return size_type(-1)/sizeof(T); }
+ { return std::size_t(-1)/(2*sizeof(T)); }
//!Swaps two allocators, does nothing
//!because this new_allocator is stateless
diff --git a/boost/container/options.hpp b/boost/container/options.hpp
index 2ac7783e46..ce8566875c 100644
--- a/boost/container/options.hpp
+++ b/boost/container/options.hpp
@@ -24,6 +24,7 @@
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/intrusive/pack_options.hpp>
+#include <boost/static_assert.hpp>
namespace boost {
namespace container {
@@ -101,6 +102,65 @@ using tree_assoc_options_t = typename boost::container::tree_assoc_options<Optio
#endif
+
+////////////////////////////////////////////////////////////////
+//
+//
+// OPTIONS FOR ASSOCIATIVE HASH-BASED CONTAINERS
+//
+//
+////////////////////////////////////////////////////////////////
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+template<bool StoreHash>
+struct hash_opt
+{
+ static const bool store_hash = StoreHash;
+};
+
+typedef hash_opt<false> hash_assoc_defaults;
+
+#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+//!This option setter specifies if node size is optimized
+//!storing rebalancing data masked into pointers for ordered associative containers
+BOOST_INTRUSIVE_OPTION_CONSTANT(store_hash, bool, Enabled, store_hash)
+
+//! Helper metafunction to combine options into a single type to be used
+//! by \c boost::container::hash_set, \c boost::container::hash_multiset
+//! \c boost::container::hash_map and \c boost::container::hash_multimap.
+//! Supported options are: \c boost::container::store_hash
+#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+template<class ...Options>
+#else
+template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
+#endif
+struct hash_assoc_options
+{
+ /// @cond
+ typedef typename ::boost::intrusive::pack_options
+ < hash_assoc_defaults,
+ #if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
+ typedef hash_opt<packed_options::store_hash> implementation_defined;
+ /// @endcond
+ typedef implementation_defined type;
+};
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+//! Helper alias metafunction to combine options into a single type to be used
+//! by hash-based associative containers
+template<class ...Options>
+using hash_assoc_options_t = typename boost::container::hash_assoc_options<Options...>::type;
+
+#endif
+
////////////////////////////////////////////////////////////////
//
//
@@ -111,6 +171,22 @@ using tree_assoc_options_t = typename boost::container::tree_assoc_options<Optio
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+template<class T, class Default>
+struct default_if_void
+{
+ typedef T type;
+};
+
+template<class Default>
+struct default_if_void<void, Default>
+{
+ typedef Default type;
+};
+
+#endif
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
template<class AllocTraits, class StoredSizeType>
struct get_stored_size_type_with_alloctraits
{
@@ -177,7 +253,7 @@ BOOST_INTRUSIVE_OPTION_TYPE(growth_factor, GrowthFactor, GrowthFactor, growth_fa
//!This option specifies the unsigned integer type that a user wants the container
//!to use to hold size-related information inside a container (e.g. current size, current capacity).
//!
-//!\tparam StoredSizeType A unsigned integer type. It shall be smaller than than the size
+//!\tparam StoredSizeType An unsigned integer type. It shall be smaller than than the size
//! of the size_type deduced from `allocator_traits<A>::size_type` or the same type.
//!
//!If the maximum capacity() to be used is limited, a user can try to use 8-bit, 16-bit
@@ -185,7 +261,7 @@ BOOST_INTRUSIVE_OPTION_TYPE(growth_factor, GrowthFactor, GrowthFactor, growth_fa
//!memory can be saved for empty vectors. This could potentially performance benefits due to better
//!cache usage.
//!
-//!Note that alignment requirements can disallow theoritical space savings. Example:
+//!Note that alignment requirements can disallow theoretical space savings. Example:
//!\c vector holds a pointer and two size types (for size and capacity), in a 32 bit machine
//!a 8 bit size type (total size: 4 byte pointer + 2 x 1 byte sizes = 6 bytes)
//!will not save space when comparing two 16-bit size types because usually
@@ -236,6 +312,206 @@ using vector_options_t = typename boost::container::vector_options<Options...>::
#endif
+////////////////////////////////////////////////////////////////
+//
+//
+// OPTIONS FOR SMALL-VECTOR CONTAINER
+//
+//
+////////////////////////////////////////////////////////////////
+
+//! This option specifies the desired alignment for the value_type stored
+//! in the container.
+//! A value zero represents the natural alignment.
+//!
+//!\tparam Alignment An unsigned integer value. Must be power of two.
+BOOST_INTRUSIVE_OPTION_CONSTANT(inplace_alignment, std::size_t, Alignment, inplace_alignment)
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+template<class GrowthType, std::size_t InplaceAlignment>
+struct small_vector_opt
+{
+ typedef GrowthType growth_factor_type;
+ static const std::size_t inplace_alignment = InplaceAlignment;
+};
+
+typedef small_vector_opt<void, 0u> small_vector_null_opt;
+
+#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+//! Helper metafunction to combine options into a single type to be used
+//! by \c boost::container::small_vector.
+//! Supported options are: \c boost::container::growth_factor and \c boost::container::inplace_alignment
+#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+template<class ...Options>
+#else
+template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
+#endif
+struct small_vector_options
+{
+ /// @cond
+ typedef typename ::boost::intrusive::pack_options
+ < small_vector_null_opt,
+ #if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
+ typedef small_vector_opt< typename packed_options::growth_factor_type
+ , packed_options::inplace_alignment> implementation_defined;
+ /// @endcond
+ typedef implementation_defined type;
+};
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+//! Helper alias metafunction to combine options into a single type to be used
+//! by \c boost::container::small_vector.
+//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
+template<class ...Options>
+using small_vector_options_t = typename boost::container::small_vector_options<Options...>::type;
+
+#endif
+
+
+////////////////////////////////////////////////////////////////
+//
+//
+// OPTIONS FOR STATIC-VECTOR CONTAINER
+//
+//
+////////////////////////////////////////////////////////////////
+
+//!This option specifies if the container will throw if in
+//!the static capacity is not sufficient to hold the required
+//!values. If false is specified, insufficient capacity will
+//!lead to BOOST_ASSERT, and if this assertion returns, to undefined behaviour,
+//!which potentially can lead to better static_vector performance.
+//!The default value is true.
+//!
+//!\tparam ThrowOnExhaustion A boolean value. True if throw is required.
+BOOST_INTRUSIVE_OPTION_CONSTANT(throw_on_overflow, bool, ThrowOnOverflow, throw_on_overflow)
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+template<bool ThrowOnOverflow, std::size_t InplaceAlignment>
+struct static_vector_opt
+{
+ static const bool throw_on_overflow = ThrowOnOverflow;
+ static const std::size_t inplace_alignment = InplaceAlignment;
+};
+
+typedef static_vector_opt<true, 0u> static_vector_null_opt;
+
+#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+//! Helper metafunction to combine options into a single type to be used
+//! by \c boost::container::static_vector.
+//! Supported options are: \c boost::container::throw_on_overflow and \c boost::container::inplace_alignment
+#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+template<class ...Options>
+#else
+template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
+#endif
+struct static_vector_options
+{
+ /// @cond
+ typedef typename ::boost::intrusive::pack_options
+ < static_vector_null_opt,
+ #if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
+ typedef static_vector_opt< packed_options::throw_on_overflow
+ , packed_options::inplace_alignment> implementation_defined;
+ /// @endcond
+ typedef implementation_defined type;
+};
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+//! Helper alias metafunction to combine options into a single type to be used
+//! by \c boost::container::static_vector.
+//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
+template<class ...Options>
+using static_vector_options_t = typename boost::container::static_vector_options<Options...>::type;
+
+#endif
+
+
+////////////////////////////////////////////////////////////////
+//
+//
+// OPTIONS FOR DEQUE-BASED CONTAINERS
+//
+//
+////////////////////////////////////////////////////////////////
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+template<std::size_t BlockBytes, std::size_t BlockSize>
+struct deque_opt
+{
+ static const std::size_t block_bytes = BlockBytes;
+ static const std::size_t block_size = BlockSize;
+ BOOST_STATIC_ASSERT_MSG(!(block_bytes && block_size), "block_bytes and block_size can't be specified at the same time");
+};
+
+typedef deque_opt<0u, 0u> deque_null_opt;
+
+#endif
+
+//! Helper metafunction to combine options into a single type to be used
+//! by \c boost::container::deque.
+//! Supported options are: \c boost::container::block_bytes
+#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+template<class ...Options>
+#else
+template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
+#endif
+struct deque_options
+{
+ /// @cond
+ typedef typename ::boost::intrusive::pack_options
+ < deque_null_opt,
+ #if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
+ typedef deque_opt< packed_options::block_bytes, packed_options::block_size > implementation_defined;
+ /// @endcond
+ typedef implementation_defined type;
+};
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+//! Helper alias metafunction to combine options into a single type to be used
+//! by \c boost::container::deque.
+//! Supported options are: \c boost::container::block_bytes
+template<class ...Options>
+using deque_options_t = typename boost::container::deque_options<Options...>::type;
+
+#endif
+
+//!This option specifies the maximum size of a block in bytes: this delimites the number of contiguous elements
+//!that will be allocated by deque as min(1u, BlockBytes/sizeof(value_type))
+//!A value zero represents the default value.
+//!
+//!\tparam BlockBytes An unsigned integer value.
+BOOST_INTRUSIVE_OPTION_CONSTANT(block_bytes, std::size_t, BlockBytes, block_bytes)
+
+//!This option specifies the size of a block, delimites the number of contiguous elements
+//!that will be allocated by deque as BlockSize.
+//!A value zero represents the default value.
+//!
+//!\tparam BlockBytes An unsigned integer value.
+BOOST_INTRUSIVE_OPTION_CONSTANT(block_size, std::size_t, BlockSize, block_size)
} //namespace container {
} //namespace boost {
diff --git a/boost/container/pmr/resource_adaptor.hpp b/boost/container/pmr/resource_adaptor.hpp
index 33406267aa..3216350542 100644
--- a/boost/container/pmr/resource_adaptor.hpp
+++ b/boost/container/pmr/resource_adaptor.hpp
@@ -15,14 +15,44 @@
# pragma once
#endif
-#include <boost/config.hpp>
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/container_fwd.hpp>
+
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/type_traits.hpp>
+#include <boost/container/detail/std_fwd.hpp>
+
+#include <cstring>
namespace boost {
namespace container {
+
+namespace pmr_dtl {
+
+template<class T>
+struct max_allocator_alignment
+{
+ static const std::size_t value = 1;
+};
+
+template<class T>
+struct max_allocator_alignment< ::boost::container::new_allocator<T> >
+{
+ static const std::size_t value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
+};
+
+template<class T>
+struct max_allocator_alignment< std::allocator<T> >
+{
+ static const std::size_t value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
+};
+
+} //namespace pmr_dtl
+
namespace pmr {
//! An instance of resource_adaptor<Allocator> is an adaptor that wraps a memory_resource interface
@@ -57,7 +87,7 @@ class resource_adaptor_imp
void static_assert_if_not_char_allocator() const
{
//This class can only be used with allocators type char
- BOOST_STATIC_ASSERT((dtl::is_same<typename Allocator::value_type, char>::value));
+ BOOST_STATIC_ASSERT((boost::container::dtl::is_same<typename Allocator::value_type, char>::value));
}
#endif
@@ -114,15 +144,25 @@ class resource_adaptor_imp
protected:
//! <b>Returns</b>: Allocated memory obtained by calling m_alloc.allocate. The size and alignment
//! of the allocated memory shall meet the requirements for a class derived from memory_resource.
- virtual void* do_allocate(size_t bytes, size_t alignment)
- { (void)alignment; return this->ebo_alloc_t::get().allocate(bytes); }
+ virtual void* do_allocate(std::size_t bytes, std::size_t alignment)
+ {
+ if (alignment <= priv_guaranteed_allocator_alignment())
+ return this->ebo_alloc_t::get().allocate(bytes);
+ else
+ return this->priv_aligned_alloc(bytes, alignment);
+ }
//! <b>Requires</b>: p was previously allocated using A.allocate, where A == m_alloc, and not
//! subsequently deallocated.
//!
//! <b>Effects</b>: Returns memory to the allocator using m_alloc.deallocate().
- virtual void do_deallocate(void* p, size_t bytes, size_t alignment)
- { (void)alignment; this->ebo_alloc_t::get().deallocate((char*)p, bytes); }
+ virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
+ {
+ if (alignment <= priv_guaranteed_allocator_alignment())
+ this->ebo_alloc_t::get().deallocate((char*)p, bytes);
+ else
+ this->priv_aligned_dealloc(p, bytes, alignment);
+ }
//! Let p be dynamic_cast<const resource_adaptor_imp*>(&other).
//!
@@ -132,6 +172,48 @@ class resource_adaptor_imp
const resource_adaptor_imp* p = dynamic_cast<const resource_adaptor_imp*>(&other);
return p && p->ebo_alloc_t::get() == this->ebo_alloc_t::get();
}
+
+ private:
+ void * priv_aligned_alloc(std::size_t bytes, std::size_t alignment)
+ {
+ //Allocate space for requested bytes, plus alignment, plus bookeeping data
+ void *const p = this->ebo_alloc_t::get().allocate(bytes + priv_extra_bytes_for_overalignment(alignment));
+
+ if (0 != p) {
+ //Obtain the aligned address after the bookeeping data
+ void *const aligned_ptr = (void*)(((std::size_t)p + priv_extra_bytes_for_overalignment(alignment)) & ~(alignment - 1));
+
+ //Store bookeeping data. Use memcpy as the underlying memory might be unaligned for
+ //a pointer (e.g. 2 byte alignment in 32 bit, 4 byte alignment in 64 bit)
+ std::memcpy(priv_bookeeping_addr_from_aligned_ptr(aligned_ptr), &p, sizeof(p));
+ return aligned_ptr;
+ }
+ return 0;
+ }
+
+ void priv_aligned_dealloc(void *aligned_ptr, std::size_t bytes, std::size_t alignment)
+ {
+ //Obtain bookeeping data
+ void *p;
+ std::memcpy(&p, priv_bookeeping_addr_from_aligned_ptr(aligned_ptr), sizeof(p));
+ std::size_t s = bytes + priv_extra_bytes_for_overalignment(alignment);
+ this->ebo_alloc_t::get().deallocate((char*)p, s);
+ }
+
+ static BOOST_CONTAINER_FORCEINLINE void *priv_bookeeping_addr_from_aligned_ptr(void *aligned_ptr)
+ {
+ return reinterpret_cast<void*>(reinterpret_cast<std::size_t>(aligned_ptr) - sizeof(void*));
+ }
+
+ BOOST_CONTAINER_FORCEINLINE static std::size_t priv_extra_bytes_for_overalignment(std::size_t alignment)
+ {
+ return alignment - 1 + sizeof(void*);
+ }
+
+ BOOST_CONTAINER_FORCEINLINE static std::size_t priv_guaranteed_allocator_alignment()
+ {
+ return pmr_dtl::max_allocator_alignment<Allocator>::value;
+ }
};
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -190,4 +272,6 @@ class resource_adaptor
} //namespace container {
} //namespace boost {
+#include <boost/container/detail/config_end.hpp>
+
#endif //BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
diff --git a/boost/container/set.hpp b/boost/container/set.hpp
index 44bad8c65b..ca6334fed8 100644
--- a/boost/container/set.hpp
+++ b/boost/container/set.hpp
@@ -1024,13 +1024,11 @@ set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Alloca
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class Key, class Compare, class Options, class Allocator>
+template <class Key, class Compare, class Allocator, class Options>
struct has_trivial_destructor_after_move<boost::container::set<Key, Compare, Allocator, Options> >
{
- typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
- ::boost::has_trivial_destructor_after_move<pointer>::value &&
- ::boost::has_trivial_destructor_after_move<Compare>::value;
+ typedef ::boost::container::dtl::tree<Key, void, Compare, Allocator, Options> tree;
+ static const bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
};
namespace container {
@@ -1693,10 +1691,8 @@ multiset(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocato
template <class Key, class Compare, class Allocator, class Options>
struct has_trivial_destructor_after_move<boost::container::multiset<Key, Compare, Allocator, Options> >
{
- typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
- ::boost::has_trivial_destructor_after_move<pointer>::value &&
- ::boost::has_trivial_destructor_after_move<Compare>::value;
+ typedef ::boost::container::dtl::tree<Key, void, Compare, Allocator, Options> tree;
+ static const bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
};
namespace container {
diff --git a/boost/container/slist.hpp b/boost/container/slist.hpp
index a37851decd..d10cf5748f 100644
--- a/boost/container/slist.hpp
+++ b/boost/container/slist.hpp
@@ -81,7 +81,7 @@ struct slist_node
typedef T internal_type;
typedef typename slist_hook<VoidPointer>::type hook_type;
- typedef typename aligned_storage<sizeof(T), alignment_of<T>::value>::type storage_t;
+ typedef typename dtl::aligned_storage<sizeof(T), dtl::alignment_of<T>::value>::type storage_t;
storage_t m_storage;
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000)
@@ -395,7 +395,7 @@ class slist
//! <b>Complexity</b>: Linear to the number of elements in x.
slist& operator= (BOOST_COPY_ASSIGN_REF(slist) x)
{
- if (&x != this){
+ if (BOOST_LIKELY(this != &x)) {
NodeAlloc &this_alloc = this->node_alloc();
const NodeAlloc &x_alloc = x.node_alloc();
dtl::bool_<allocator_traits_type::
@@ -424,26 +424,27 @@ class slist
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value)
{
- BOOST_ASSERT(this != &x);
- NodeAlloc &this_alloc = this->node_alloc();
- NodeAlloc &x_alloc = x.node_alloc();
- const bool propagate_alloc = allocator_traits_type::
- propagate_on_container_move_assignment::value;
- const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
- //Resources can be transferred if both allocators are
- //going to be equal after this function (either propagated or already equal)
- if(propagate_alloc || allocators_equal){
- //Destroy
- this->clear();
- //Move allocator if needed
- this->AllocHolder::move_assign_alloc(x);
- //Obtain resources
- this->icont() = boost::move(x.icont());
- }
- //Else do a one by one move
- else{
- this->assign( boost::make_move_iterator(x.begin())
- , boost::make_move_iterator(x.end()));
+ if (BOOST_LIKELY(this != &x)) {
+ NodeAlloc &this_alloc = this->node_alloc();
+ NodeAlloc &x_alloc = x.node_alloc();
+ const bool propagate_alloc = allocator_traits_type::
+ propagate_on_container_move_assignment::value;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ //Destroy
+ this->clear();
+ //Move allocator if needed
+ this->AllocHolder::move_assign_alloc(x);
+ //Obtain resources
+ this->icont() = boost::move(x.icont());
+ }
+ //Else do a one by one move
+ else{
+ this->assign( boost::make_move_iterator(x.begin())
+ , boost::make_move_iterator(x.end()));
+ }
}
return *this;
}
@@ -1695,8 +1696,9 @@ namespace boost {
template <class T, class Allocator>
struct has_trivial_destructor_after_move<boost::container::slist<T, Allocator> >
{
- typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ typedef typename boost::container::slist<T, Allocator>::allocator_type allocator_type;
+ typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value;
};
diff --git a/boost/container/small_vector.hpp b/boost/container/small_vector.hpp
index 83f1cad144..6529a82628 100644
--- a/boost/container/small_vector.hpp
+++ b/boost/container/small_vector.hpp
@@ -48,12 +48,48 @@
namespace boost {
namespace container {
-#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+namespace dtl{
-template <class T, class Allocator = void >
-class small_vector_base;
+template<class Options>
+struct get_small_vector_opt
+{
+ typedef Options type;
+};
-#endif
+template<>
+struct get_small_vector_opt<void>
+{
+ typedef small_vector_null_opt type;
+};
+
+template<class Options>
+struct get_vopt_from_svopt
+ : get_small_vector_opt<Options>::type
+{
+ typedef typename get_small_vector_opt<Options>::type options_t;
+ typedef vector_opt< typename options_t::growth_factor_type, void> type;
+};
+
+template<>
+struct get_vopt_from_svopt<void>
+{
+ typedef void type;
+};
+
+template <class T, class SecondaryAllocator, class Options>
+struct vector_for_small_vector
+{
+ typedef vector
+ < T
+ , small_vector_allocator
+ < T
+ , typename allocator_traits<typename real_allocator<T, SecondaryAllocator>::type>::template portable_rebind_alloc<void>::type
+ , Options>
+ , typename dtl::get_vopt_from_svopt<Options>::type
+ > type;
+};
+
+} //namespace dtl
//! A non-standard allocator used to implement `small_vector`.
//! Users should never use it directly. It is described here
@@ -81,7 +117,7 @@ class small_vector_base;
//! `boost::container::vector< T, small_vector_allocator<T, Allocator> >`
//! and internal storage can be obtained downcasting that vector
//! to `small_vector_base<T>`.
-template<class T, class VoidAllocator>
+template<class T, class VoidAllocator BOOST_CONTAINER_DOCONLY(= void), class Options BOOST_CONTAINER_DOCONLY(= void)>
class small_vector_allocator
: public allocator_traits<typename real_allocator<T, VoidAllocator>::type>::template portable_rebind_alloc<T>::type
{
@@ -93,10 +129,10 @@ class small_vector_allocator
BOOST_COPYABLE_AND_MOVABLE(small_vector_allocator)
- BOOST_CONTAINER_FORCEINLINE const allocator_type &as_base() const
+ BOOST_CONTAINER_FORCEINLINE const allocator_type &as_base() const BOOST_NOEXCEPT
{ return static_cast<const allocator_type&>(*this); }
- BOOST_CONTAINER_FORCEINLINE allocator_type &as_base()
+ BOOST_CONTAINER_FORCEINLINE allocator_type &as_base() BOOST_NOEXCEPT
{ return static_cast<allocator_type&>(*this); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -134,22 +170,8 @@ class small_vector_allocator
typedef typename allocator_traits<allocator_type>::template portable_rebind_alloc<T2>::type other;
};
- #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- //!Constructor from arbitrary arguments
- template<class ...Args>
- BOOST_CONTAINER_FORCEINLINE explicit small_vector_allocator(BOOST_FWD_REF(Args) ...args)
- : allocator_type(::boost::forward<Args>(args)...)
- {}
- #else
- #define BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE(N) \
- BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- BOOST_CONTAINER_FORCEINLINE explicit small_vector_allocator(BOOST_MOVE_UREF##N)\
- : allocator_type(BOOST_MOVE_FWD##N)\
- {}\
- //
- BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE)
- #undef BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE
- #endif
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
+ {}
//!Constructor from other small_vector_allocator.
//!Never throws
@@ -167,27 +189,34 @@ class small_vector_allocator
//!Constructor from related small_vector_allocator.
//!Never throws
- template<class U, class OtherVoidAllocator>
+ template<class U, class OtherVoidAllocator, class OtherOptions>
BOOST_CONTAINER_FORCEINLINE small_vector_allocator
- (const small_vector_allocator<U, OtherVoidAllocator> &other) BOOST_NOEXCEPT_OR_NOTHROW
+ (const small_vector_allocator<U, OtherVoidAllocator, OtherOptions> &other) BOOST_NOEXCEPT_OR_NOTHROW
: allocator_type(other.as_base())
{}
//!Move constructor from related small_vector_allocator.
//!Never throws
- template<class U, class OtherVoidAllocator>
+ template<class U, class OtherVoidAllocator, class OtherOptions>
BOOST_CONTAINER_FORCEINLINE small_vector_allocator
- (BOOST_RV_REF(small_vector_allocator<U BOOST_MOVE_I OtherVoidAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
+ (BOOST_RV_REF(small_vector_allocator<U BOOST_MOVE_I OtherVoidAllocator BOOST_MOVE_I OtherOptions>) other) BOOST_NOEXCEPT_OR_NOTHROW
: allocator_type(::boost::move(other.as_base()))
{}
+ //!Constructor from allocator_type.
+ //!Never throws
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector_allocator
+ (const allocator_type &other) BOOST_NOEXCEPT_OR_NOTHROW
+ : allocator_type(other)
+ {}
+
//!Assignment from other small_vector_allocator.
//!Never throws
BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
{ return static_cast<small_vector_allocator&>(this->allocator_type::operator=(other.as_base())); }
- //!Move constructor from other small_vector_allocator.
+ //!Move assignment from other small_vector_allocator.
//!Never throws
BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
operator=(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
@@ -197,16 +226,22 @@ class small_vector_allocator
//!Never throws
template<class U, class OtherVoidAllocator>
BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
- operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator<U BOOST_MOVE_I OtherVoidAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
+ operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator<U BOOST_MOVE_I OtherVoidAllocator BOOST_MOVE_I Options>) other) BOOST_NOEXCEPT_OR_NOTHROW
{ return static_cast<small_vector_allocator&>(this->allocator_type::operator=(other.as_base())); }
//!Move assignment from related small_vector_allocator.
//!Never throws
template<class U, class OtherVoidAllocator>
BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
- operator=(BOOST_RV_REF(small_vector_allocator<U BOOST_MOVE_I OtherVoidAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
+ operator=(BOOST_RV_REF(small_vector_allocator<U BOOST_MOVE_I OtherVoidAllocator BOOST_MOVE_I Options>) other) BOOST_NOEXCEPT_OR_NOTHROW
{ return static_cast<small_vector_allocator&>(this->allocator_type::operator=(::boost::move(other.as_base()))); }
+ //!Move assignment from allocator_type.
+ //!Never throws
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
+ operator=(const allocator_type &other) BOOST_NOEXCEPT_OR_NOTHROW
+ { return static_cast<small_vector_allocator&>(this->allocator_type::operator=(other)); }
+
//!Allocates storage from the standard-conforming allocator
BOOST_CONTAINER_FORCEINLINE pointer allocate(size_type count, const_void_pointer hint = const_void_pointer())
{ return allocator_traits_type::allocate(this->as_base(), count, hint); }
@@ -279,8 +314,8 @@ class small_vector_allocator
using allocator_type::deallocate_many;*/
typedef vector_alloc_holder< small_vector_allocator, size_type > vector_alloc_holder_t;
- typedef vector<value_type, small_vector_allocator> vector_base;
- typedef small_vector_base<value_type, allocator_type> derived_type;
+ typedef typename dtl::vector_for_small_vector<T, allocator_type, Options>::type vector_base;
+ typedef small_vector_base<value_type, allocator_type, Options> derived_type;
BOOST_CONTAINER_FORCEINLINE bool is_internal_storage(const_pointer p) const
{ return this->internal_storage() == p; }
@@ -330,33 +365,30 @@ class small_vector_allocator
//!
//! All `boost::container:vector` member functions are inherited. See `vector` documentation for details.
//!
-template <class T, class SecondaryAllocator>
+template <class T, class SecondaryAllocator, class Options>
class small_vector_base
- : public vector
- < T
- , small_vector_allocator
- < T
- , typename allocator_traits<typename real_allocator<T, SecondaryAllocator>::type>::template portable_rebind_alloc<void>::type
- >
- >
+ : public dtl::vector_for_small_vector<T, SecondaryAllocator, Options>::type
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKEDVECTOR
public:
//Make it public as it will be inherited by small_vector and container
//must have this public member
- typedef typename real_allocator<T, SecondaryAllocator>::type secondary_allocator_t;
- typedef typename allocator_traits<secondary_allocator_t>::template portable_rebind_alloc<void>::type void_allocator_t;
- typedef vector<T, small_vector_allocator<T, void_allocator_t> > base_type;
- typedef typename allocator_traits<secondary_allocator_t>::pointer pointer;
- typedef typename allocator_traits<secondary_allocator_t>::const_pointer const_pointer;
- typedef typename allocator_traits<secondary_allocator_t>::void_pointer void_pointer;
+ typedef typename real_allocator<T, SecondaryAllocator>::type secondary_allocator_t;
+ typedef typename allocator_traits<secondary_allocator_t>::
+ template portable_rebind_alloc<void>::type void_allocator_t;
+ typedef typename dtl::get_small_vector_opt<Options>::type options_t;
+ typedef typename dtl::vector_for_small_vector
+ <T, SecondaryAllocator, Options>::type base_type;
+ typedef typename allocator_traits<secondary_allocator_t>::pointer pointer;
+ typedef typename allocator_traits<secondary_allocator_t>::const_pointer const_pointer;
+ typedef typename allocator_traits<secondary_allocator_t>::void_pointer void_pointer;
typedef typename allocator_traits<secondary_allocator_t>::const_void_pointer const_void_pointer;
- typedef small_vector_allocator<T, void_allocator_t> allocator_type;
+ typedef small_vector_allocator<T, void_allocator_t, Options> allocator_type;
private:
BOOST_COPYABLE_AND_MOVABLE(small_vector_base)
- friend class small_vector_allocator<T, void_allocator_t>;
+ friend class small_vector_allocator<T, void_allocator_t, Options>;
BOOST_CONTAINER_FORCEINLINE
const_pointer internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW
@@ -381,9 +413,12 @@ class small_vector_base
base_type &as_base() { return static_cast<base_type&>(*this); }
const base_type &as_base() const { return static_cast<const base_type&>(*this); }
+ static const std::size_t final_alignment =
+ options_t::inplace_alignment ? options_t::inplace_alignment : dtl::alignment_of<T>::value;
public:
+
typedef typename dtl::aligned_storage
- <sizeof(T), dtl::alignment_of<T>::value>::type storage_type;
+ <sizeof(T), final_alignment>::type storage_type;
protected:
@@ -449,13 +484,14 @@ struct small_vector_storage_calculator_helper<Needed, Hdr, SSize, true>
static const std::size_t value = 0u;
};
-template<class Storage, class Allocator, class T, std::size_t N>
+template<class Storage, class Allocator, class T, std::size_t N, class Options>
struct small_vector_storage_calculator
{
- typedef small_vector_base<T, Allocator> svh_type;
+ typedef small_vector_base<T, Allocator, Options> svh_type;
typedef typename real_allocator<T, Allocator>::type value_allocator_t;
typedef typename allocator_traits<value_allocator_t>::template portable_rebind_alloc<void>::type void_allocator_t;
- typedef vector<T, small_vector_allocator<T, void_allocator_t> > svhb_type;
+ typedef typename dtl::vector_for_small_vector<T, void_allocator_t, Options>::type svhb_type;
+
static const std::size_t s_align = dtl::alignment_of<Storage>::value;
static const std::size_t s_size = sizeof(Storage);
static const std::size_t svh_sizeof = sizeof(svh_type);
@@ -482,13 +518,13 @@ template<class Storage>
struct small_vector_storage<Storage, 0>
{};
-template<class T, class Allocator, std::size_t N>
+template<class T, class Allocator, std::size_t N, class Options>
struct small_vector_storage_definer
{
typedef T value_type;
- typedef typename small_vector_base<value_type, Allocator>::storage_type storage_type;
+ typedef typename small_vector_base<value_type, Allocator, Options>::storage_type storage_type;
static const std::size_t needed_extra_storages =
- small_vector_storage_calculator<storage_type, Allocator, value_type, N>::needed_extra_storages;
+ small_vector_storage_calculator<storage_type, Allocator, value_type, N, Options>::needed_extra_storages;
typedef small_vector_storage<storage_type, needed_extra_storages> type;
};
@@ -498,7 +534,7 @@ struct small_vector_storage_definer
//! It contains some preallocated elements in-place, which can avoid the use of dynamic storage allocation
//! when the actual number of elements is below that preallocated threshold.
//!
-//! `small_vector<T, N, Allocator>` is convertible to `small_vector_base<T, Allocator>` that is independent
+//! `small_vector<T, N, Allocator, Options>` is convertible to `small_vector_base<T, Allocator, Options>` that is independent
//! from the preallocated element capacity, so client code does not need to be templated on that N argument.
//!
//! All `boost::container::vector` member functions are inherited. See `vector` documentation for details.
@@ -507,23 +543,26 @@ struct small_vector_storage_definer
//! \tparam N The number of preallocated elements stored inside small_vector. It shall be less than Allocator::max_size();
//! \tparam Allocator The allocator used for memory management when the number of elements exceeds N. Use void
//! for the default allocator
-template <class T, std::size_t N, class Allocator BOOST_CONTAINER_DOCONLY(= void) >
-class small_vector : public small_vector_base<T, Allocator>
+//! |tparam Options A type produced from \c boost::container::small_vector_options.
+template <class T, std::size_t N, class Allocator BOOST_CONTAINER_DOCONLY(= void), class Options BOOST_CONTAINER_DOCONLY(= void) >
+class small_vector : public small_vector_base<T, Allocator, Options>
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
- , private small_vector_storage_definer<T, Allocator, N>::type
+ , private small_vector_storage_definer<T, Allocator, N, Options>::type
#endif
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
- typedef small_vector_base<T, Allocator> base_type;
- typedef typename small_vector_storage_definer<T, Allocator, N>::type remaining_storage_holder;
+ typedef small_vector_base<T, Allocator, Options> base_type;
+ typedef typename small_vector_storage_definer
+ <T, Allocator, N, Options>::type remaining_storage_holder;
BOOST_COPYABLE_AND_MOVABLE(small_vector)
typedef allocator_traits<typename base_type::allocator_type> allocator_traits_type;
public:
- typedef small_vector_storage_calculator< typename small_vector_base<T, Allocator>
- ::storage_type, Allocator, T, N> storage_test;
+ typedef small_vector_storage_calculator
+ < typename small_vector_base<T, Allocator, Options>::storage_type
+ , Allocator, T, N, Options> storage_test;
static const std::size_t needed_extra_storages = storage_test::needed_extra_storages;
static const std::size_t needed_bytes = storage_test::needed_bytes;
@@ -544,7 +583,7 @@ class small_vector : public small_vector_base<T, Allocator>
public:
BOOST_CONTAINER_FORCEINLINE small_vector()
- BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+ BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
: base_type(initial_capacity_t(), internal_capacity())
{}
diff --git a/boost/container/stable_vector.hpp b/boost/container/stable_vector.hpp
index 92ef0f6a7f..7d0c9b3995 100644
--- a/boost/container/stable_vector.hpp
+++ b/boost/container/stable_vector.hpp
@@ -337,7 +337,7 @@ class stable_vector_iterator
: m_pn(other.node_pointer())
{}
- stable_vector_iterator(const nonconst_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE stable_vector_iterator(const nonconst_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
: m_pn(other.node_pointer())
{}
@@ -823,7 +823,7 @@ class stable_vector
stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x)
{
STABLE_VECTOR_CHECK_INVARIANT;
- if (&x != this){
+ if (BOOST_LIKELY(this != &x)) {
node_allocator_type &this_alloc = this->priv_node_alloc();
const node_allocator_type &x_alloc = x.priv_node_alloc();
dtl::bool_<allocator_traits_type::
@@ -855,29 +855,30 @@ class stable_vector
|| allocator_traits_type::is_always_equal::value)
{
//for move constructor, no aliasing (&x != this) is assumed.
- BOOST_ASSERT(this != &x);
- node_allocator_type &this_alloc = this->priv_node_alloc();
- node_allocator_type &x_alloc = x.priv_node_alloc();
- const bool propagate_alloc = allocator_traits_type::
- propagate_on_container_move_assignment::value;
- dtl::bool_<propagate_alloc> flag;
- const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
- //Resources can be transferred if both allocators are
- //going to be equal after this function (either propagated or already equal)
- if(propagate_alloc || allocators_equal){
- STABLE_VECTOR_CHECK_INVARIANT
- //Destroy objects but retain memory in case x reuses it in the future
- this->clear();
- //Move allocator if needed
- dtl::move_alloc(this_alloc, x_alloc, flag);
- //Take resources
- this->index.swap(x.index);
- this->priv_swap_members(x);
- }
- //Else do a one by one move
- else{
- this->assign( boost::make_move_iterator(x.begin())
- , boost::make_move_iterator(x.end()));
+ if (BOOST_LIKELY(this != &x)) {
+ node_allocator_type &this_alloc = this->priv_node_alloc();
+ node_allocator_type &x_alloc = x.priv_node_alloc();
+ const bool propagate_alloc = allocator_traits_type::
+ propagate_on_container_move_assignment::value;
+ dtl::bool_<propagate_alloc> flag;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ STABLE_VECTOR_CHECK_INVARIANT
+ //Destroy objects but retain memory in case x reuses it in the future
+ this->clear();
+ //Move allocator if needed
+ dtl::move_alloc(this_alloc, x_alloc, flag);
+ //Take resources
+ this->index.swap(x.index);
+ this->priv_swap_members(x);
+ }
+ //Else do a one by one move
+ else{
+ this->assign( boost::make_move_iterator(x.begin())
+ , boost::make_move_iterator(x.end()));
+ }
}
return *this;
}
@@ -2182,8 +2183,9 @@ stable_vector(InputIterator, InputIterator, Allocator const&) ->
template <class T, class Allocator>
struct has_trivial_destructor_after_move<boost::container::stable_vector<T, Allocator> >
{
- typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ typedef typename boost::container::stable_vector<T, Allocator>::allocator_type allocator_type;
+ typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value;
};
diff --git a/boost/container/static_vector.hpp b/boost/container/static_vector.hpp
index 059640e937..2c08be88b6 100644
--- a/boost/container/static_vector.hpp
+++ b/boost/container/static_vector.hpp
@@ -35,9 +35,21 @@ namespace boost { namespace container {
namespace dtl {
-template<class T, std::size_t N>
+template<class T, std::size_t N, std::size_t InplaceAlignment, bool ThrowOnOverflow>
class static_storage_allocator
{
+ typedef bool_<ThrowOnOverflow> throw_on_overflow_t;
+
+ static BOOST_NORETURN BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow(true_type)
+ {
+ (throw_bad_alloc)();
+ }
+
+ static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow(false_type)
+ {
+ BOOST_ASSERT_MSG(false, "ERROR: static vector capacity overflow");
+ }
+
public:
typedef T value_type;
@@ -61,6 +73,11 @@ class static_storage_allocator
std::size_t max_size() const
{ return N; }
+ static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow()
+ {
+ (on_capacity_overflow)(throw_on_overflow_t());
+ }
+
typedef boost::container::dtl::version_type<static_storage_allocator, 0> version;
BOOST_CONTAINER_FORCEINLINE friend bool operator==(const static_storage_allocator &, const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
@@ -70,9 +87,36 @@ class static_storage_allocator
{ return true; }
private:
- typename aligned_storage<sizeof(T)*N, alignment_of<T>::value>::type storage;
+ BOOST_STATIC_ASSERT_MSG(!InplaceAlignment || (InplaceAlignment & (InplaceAlignment-1)) == 0, "Alignment option must be zero or power of two");
+ static const std::size_t final_alignment = InplaceAlignment ? InplaceAlignment : dtl::alignment_of<T>::value;
+ typename dtl::aligned_storage<sizeof(T)*N, final_alignment>::type storage;
+};
+
+template<class Options>
+struct get_static_vector_opt
+{
+ typedef Options type;
+};
+
+template<>
+struct get_static_vector_opt<void>
+{
+ typedef static_vector_null_opt type;
};
+template <typename T, std::size_t Capacity, class Options>
+struct get_static_vector_allocator
+{
+ typedef typename get_static_vector_opt<Options>::type options_t;
+ typedef dtl::static_storage_allocator
+ < T
+ , Capacity
+ , options_t::inplace_alignment
+ , options_t::throw_on_overflow
+ > type;
+};
+
+
} //namespace dtl {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -99,22 +143,24 @@ class static_storage_allocator
//! std::out_of_range is thrown if out of bounds access is performed in <code>at()</code> if exceptions are
//! enabled, throw_out_of_range() if not enabled.
//!
-//!@tparam Value The type of element that will be stored.
+//!@tparam T The type of element that will be stored.
//!@tparam Capacity The maximum number of elements static_vector can store, fixed at compile time.
-template <typename Value, std::size_t Capacity>
+//!@tparam Options A type produced from \c boost::container::static_vector_options.
+template <typename T, std::size_t Capacity, class Options BOOST_CONTAINER_DOCONLY(= void) >
class static_vector
- : public vector<Value, dtl::static_storage_allocator<Value, Capacity> >
+ : public vector<T, typename dtl::get_static_vector_allocator< T, Capacity, Options>::type>
{
+ public:
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
- typedef vector<Value, dtl::static_storage_allocator<Value, Capacity> > base_t;
+ typedef typename dtl::get_static_vector_allocator< T, Capacity, Options>::type allocator_type;
+ typedef vector<T, allocator_type > base_t;
BOOST_COPYABLE_AND_MOVABLE(static_vector)
- template<class U, std::size_t OtherCapacity>
+ template<class U, std::size_t OtherCapacity, class OtherOptions>
friend class static_vector;
public:
- typedef dtl::static_storage_allocator<Value, Capacity> allocator_type;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
@@ -162,7 +208,7 @@ public:
//! @param count The number of values which will be contained in the container.
//!
//! @par Throws
- //! If Value's value initialization throws.
+ //! If T's value initialization throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -177,7 +223,7 @@ public:
//! @param count The number of values which will be contained in the container.
//!
//! @par Throws
- //! If Value's default initialization throws.
+ //! If T's default initialization throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -196,7 +242,7 @@ public:
//! @param value The value which will be used to copy construct values.
//!
//! @par Throws
- //! If Value's copy constructor throws.
+ //! If T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -214,7 +260,7 @@ public:
//! @param last The iterator to the one after the last element in range.
//!
//! @par Throws
- //! If Value's constructor taking a dereferenced Iterator throws.
+ //! If T's constructor taking a dereferenced Iterator throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -232,7 +278,7 @@ public:
//! @param il std::initializer_list with values to initialize vector.
//!
//! @par Throws
- //! If Value's constructor taking a dereferenced std::initializer_list throws.
+ //! If T's constructor taking a dereferenced std::initializer_list throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -246,7 +292,7 @@ public:
//! @param other The static_vector which content will be copied to this one.
//!
//! @par Throws
- //! If Value's copy constructor throws.
+ //! If T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -274,12 +320,12 @@ public:
//! @param other The static_vector which content will be copied to this one.
//!
//! @par Throws
- //! If Value's copy constructor throws.
+ //! If T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
- template <std::size_t C>
- BOOST_CONTAINER_FORCEINLINE static_vector(static_vector<value_type, C> const& other)
+ template <std::size_t C, class O>
+ BOOST_CONTAINER_FORCEINLINE static_vector(static_vector<T, C, O> const& other)
: base_t(other)
{}
@@ -288,8 +334,8 @@ public:
//! @param other The static_vector which content will be moved to this one.
//!
//! @par Throws
- //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
- //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor throws.
+ //! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -305,14 +351,14 @@ public:
//! @param other The static_vector which content will be moved to this one.
//!
//! @par Throws
- //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
- //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor throws.
+ //! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
- template <std::size_t C>
- BOOST_CONTAINER_FORCEINLINE static_vector(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
- : base_t(BOOST_MOVE_BASE(typename static_vector<value_type BOOST_MOVE_I C>::base_t, other))
+ template <std::size_t C, class O>
+ BOOST_CONTAINER_FORCEINLINE static_vector(BOOST_RV_REF_BEG static_vector<T, C, O> BOOST_RV_REF_END other)
+ : base_t(BOOST_MOVE_BASE(typename static_vector<T BOOST_MOVE_I C>::base_t, other))
{}
//! @brief Copy assigns Values stored in the other static_vector to this one.
@@ -320,7 +366,7 @@ public:
//! @param other The static_vector which content will be copied to this one.
//!
//! @par Throws
- //! If Value's copy constructor or copy assignment throws.
+ //! If T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -335,7 +381,7 @@ public:
//! @param il The std::initializer_list which content will be copied to this one.
//!
//! @par Throws
- //! If Value's copy constructor or copy assignment throws.
+ //! If T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -350,15 +396,15 @@ public:
//! @param other The static_vector which content will be copied to this one.
//!
//! @par Throws
- //! If Value's copy constructor or copy assignment throws.
+ //! If T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
- template <std::size_t C>
- BOOST_CONTAINER_FORCEINLINE static_vector & operator=(static_vector<value_type, C> const& other)
+ template <std::size_t C, class O>
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(static_vector<T, C, O> const& other)
{
return static_cast<static_vector&>(base_t::operator=
- (static_cast<typename static_vector<value_type, C>::base_t const&>(other)));
+ (static_cast<typename static_vector<T, C, O>::base_t const&>(other)));
}
//! @brief Move assignment. Moves Values stored in the other static_vector to this one.
@@ -366,8 +412,8 @@ public:
//! @param other The static_vector which content will be moved to this one.
//!
//! @par Throws
- //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
- //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor or move assignment throws.
+ //! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -384,16 +430,16 @@ public:
//! @param other The static_vector which content will be moved to this one.
//!
//! @par Throws
- //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
- //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor or move assignment throws.
+ //! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
- template <std::size_t C>
- BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
+ template <std::size_t C, class O>
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_RV_REF_BEG static_vector<T, C, O> BOOST_RV_REF_END other)
{
return static_cast<static_vector&>(base_t::operator=
- (BOOST_MOVE_BASE(typename static_vector<value_type BOOST_MOVE_I C>::base_t, other)));
+ (BOOST_MOVE_BASE(typename static_vector<T BOOST_MOVE_I C>::base_t, other)));
}
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -412,8 +458,8 @@ public:
//! @param other The static_vector which content will be swapped with this one's content.
//!
//! @par Throws
- //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
- //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor or move assignment throws,
+ //! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor or copy assignment throws,
//!
//! @par Complexity
//! Linear O(N).
@@ -426,13 +472,13 @@ public:
//! @param other The static_vector which content will be swapped with this one's content.
//!
//! @par Throws
- //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
- //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //! @li If \c has_nothrow_move<T>::value is \c true and T's move constructor or move assignment throws,
+ //! @li If \c has_nothrow_move<T>::value is \c false and T's copy constructor or copy assignment throws,
//!
//! @par Complexity
//! Linear O(N).
- template <std::size_t C>
- void swap(static_vector<value_type, C> & other);
+ template <std::size_t C, class O>
+ void swap(static_vector<T, C, O> & other);
//! @pre <tt>count <= capacity()</tt>
//!
@@ -442,7 +488,7 @@ public:
//! @param count The number of elements which will be stored in the container.
//!
//! @par Throws
- //! If Value's value initialization throws.
+ //! If T's value initialization throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -456,7 +502,7 @@ public:
//! @param count The number of elements which will be stored in the container.
//!
//! @par Throws
- //! If Value's default initialization throws.
+ //! If T's default initialization throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -474,7 +520,7 @@ public:
//! @param value The value used to copy construct the new element.
//!
//! @par Throws
- //! If Value's copy constructor throws.
+ //! If T's copy constructor throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -500,7 +546,7 @@ public:
//! @param value The value used to copy construct the new element.
//!
//! @par Throws
- //! If Value's copy constructor throws.
+ //! If T's copy constructor throws.
//!
//! @par Complexity
//! Constant O(1).
@@ -513,7 +559,7 @@ public:
//! @param value The value to move construct the new element.
//!
//! @par Throws
- //! If Value's move constructor throws.
+ //! If T's move constructor throws.
//!
//! @par Complexity
//! Constant O(1).
@@ -540,8 +586,8 @@ public:
//! @param value The value used to copy construct the new element.
//!
//! @par Throws
- //! @li If Value's copy constructor or copy assignment throws
- //! @li If Value's move constructor or move assignment throws.
+ //! @li If T's copy constructor or copy assignment throws
+ //! @li If T's move constructor or move assignment throws.
//!
//! @par Complexity
//! Constant or linear.
@@ -557,7 +603,7 @@ public:
//! @param value The value used to move construct the new element.
//!
//! @par Throws
- //! If Value's move constructor or move assignment throws.
+ //! If T's move constructor or move assignment throws.
//!
//! @par Complexity
//! Constant or linear.
@@ -574,8 +620,8 @@ public:
//! @param value The value used to copy construct new elements.
//!
//! @par Throws
- //! @li If Value's copy constructor or copy assignment throws.
- //! @li If Value's move constructor or move assignment throws.
+ //! @li If T's copy constructor or copy assignment throws.
+ //! @li If T's move constructor or move assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -593,8 +639,8 @@ public:
//! @param last The iterator to the one after the last element of a range used to construct new elements.
//!
//! @par Throws
- //! @li If Value's constructor and assignment taking a dereferenced \c Iterator.
- //! @li If Value's move constructor or move assignment throws.
+ //! @li If T's constructor and assignment taking a dereferenced \c Iterator.
+ //! @li If T's move constructor or move assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -611,7 +657,7 @@ public:
//! @param il The std::initializer_list which contains elements that will be inserted.
//!
//! @par Throws
- //! @li If Value's constructor and assignment taking a dereferenced std::initializer_list iterator.
+ //! @li If T's constructor and assignment taking a dereferenced std::initializer_list iterator.
//!
//! @par Complexity
//! Linear O(N).
@@ -619,12 +665,12 @@ public:
//! @pre \c p must be a valid iterator of \c *this in range <tt>[begin(), end())</tt>
//!
- //! @brief Erases Value from p.
+ //! @brief Erases T from p.
//!
//! @param p The position of the element which will be erased from the container.
//!
//! @par Throws
- //! If Value's move assignment throws.
+ //! If T's move assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -640,7 +686,7 @@ public:
//! @param last The position of the one after the last element of a range which will be erased from the container.
//!
//! @par Throws
- //! If Value's move assignment throws.
+ //! If T's move assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -654,7 +700,7 @@ public:
//! @param last The iterator to the one after the last element of a range used to construct new content of this container.
//!
//! @par Throws
- //! If Value's copy constructor or copy assignment throws,
+ //! If T's copy constructor or copy assignment throws,
//!
//! @par Complexity
//! Linear O(N).
@@ -668,7 +714,7 @@ public:
//! @param il std::initializer_list with values used to construct new content of this container.
//!
//! @par Throws
- //! If Value's copy constructor or copy assignment throws,
+ //! If T's copy constructor or copy assignment throws,
//!
//! @par Complexity
//! Linear O(N).
@@ -682,7 +728,7 @@ public:
//! @param value The value which will be used to copy construct the new content.
//!
//! @par Throws
- //! If Value's copy constructor or copy assignment throws.
+ //! If T's copy constructor or copy assignment throws.
//!
//! @par Complexity
//! Linear O(N).
@@ -690,7 +736,7 @@ public:
//! @pre <tt>size() < capacity()</tt>
//!
- //! @brief Inserts a Value constructed with
+ //! @brief Inserts a T constructed with
//! \c std::forward<Args>(args)... in the end of the container.
//!
//! @return A reference to the created object.
@@ -698,7 +744,7 @@ public:
//! @param args The arguments of the constructor of the new element which will be created at the end of the container.
//!
//! @par Throws
- //! If in-place constructor throws or Value's move constructor throws.
+ //! If in-place constructor throws or T's move constructor throws.
//!
//! @par Complexity
//! Constant O(1).
@@ -709,14 +755,14 @@ public:
//! @li \c p must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>
//! @li <tt>size() < capacity()</tt>
//!
- //! @brief Inserts a Value constructed with
+ //! @brief Inserts a T constructed with
//! \c std::forward<Args>(args)... before p
//!
//! @param p The position at which new elements will be inserted.
//! @param args The arguments of the constructor of the new element.
//!
//! @par Throws
- //! If in-place constructor throws or if Value's move constructor or move assignment throws.
+ //! If in-place constructor throws or if T's move constructor or move assignment throws.
//!
//! @par Complexity
//! Constant or linear.
@@ -920,7 +966,7 @@ public:
//!
//! @par Complexity
//! Constant O(1).
- Value * data() BOOST_NOEXCEPT_OR_NOTHROW;
+ T * data() BOOST_NOEXCEPT_OR_NOTHROW;
//! @brief Const pointer such that <tt>[data(), data() + size())</tt> is a valid range.
//! For a non-empty vector <tt>data() == &front()</tt>.
@@ -930,7 +976,7 @@ public:
//!
//! @par Complexity
//! Constant O(1).
- const Value * data() const BOOST_NOEXCEPT_OR_NOTHROW;
+ const T * data() const BOOST_NOEXCEPT_OR_NOTHROW;
//! @brief Returns iterator to the first element.
//!
@@ -1138,8 +1184,8 @@ public:
//!
//! @par Complexity
//! Linear O(N).
-template<typename V, std::size_t C1, std::size_t C2>
-bool operator== (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
+bool operator== (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Checks if contents of two static_vectors are not equal.
//!
@@ -1152,8 +1198,8 @@ bool operator== (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
-template<typename V, std::size_t C1, std::size_t C2>
-bool operator!= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
+bool operator!= (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors.
//!
@@ -1166,8 +1212,8 @@ bool operator!= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
-template<typename V, std::size_t C1, std::size_t C2>
-bool operator< (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
+bool operator< (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors.
//!
@@ -1180,8 +1226,8 @@ bool operator< (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
-template<typename V, std::size_t C1, std::size_t C2>
-bool operator> (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
+bool operator> (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors.
//!
@@ -1194,8 +1240,8 @@ bool operator> (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
-template<typename V, std::size_t C1, std::size_t C2>
-bool operator<= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
+bool operator<= (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Lexicographically compares static_vectors.
//!
@@ -1208,8 +1254,8 @@ bool operator<= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
-template<typename V, std::size_t C1, std::size_t C2>
-bool operator>= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
+bool operator>= (static_vector<V, C1, O1> const& x, static_vector<V, C2, O2> const& y);
//! @brief Swaps contents of two static_vectors.
//!
@@ -1222,13 +1268,13 @@ bool operator>= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
//!
//! @par Complexity
//! Linear O(N).
-template<typename V, std::size_t C1, std::size_t C2>
-inline void swap(static_vector<V, C1> & x, static_vector<V, C2> & y);
+template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
+inline void swap(static_vector<V, C1, O1> & x, static_vector<V, C2, O2> & y);
#else
-template<typename V, std::size_t C1, std::size_t C2>
-inline void swap(static_vector<V, C1> & x, static_vector<V, C2> & y
+template<typename V, std::size_t C1, std::size_t C2, class O1, class O2>
+inline void swap(static_vector<V, C1, O1> & x, static_vector<V, C2, O2> & y
, typename dtl::enable_if_c< C1 != C2>::type * = 0)
{
x.swap(y);
diff --git a/boost/container/string.hpp b/boost/container/string.hpp
index 46ce035c7e..46ca567a60 100644
--- a/boost/container/string.hpp
+++ b/boost/container/string.hpp
@@ -865,7 +865,7 @@ class basic_string
//! <b>Complexity</b>: Linear to the elements x contains.
basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) x)
{
- if (&x != this){
+ if (BOOST_LIKELY(this != &x)) {
allocator_type &this_alloc = this->alloc();
const allocator_type &x_alloc = x.alloc();
dtl::bool_<allocator_traits_type::
@@ -896,27 +896,27 @@ class basic_string
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value)
{
- //for move constructor, no aliasing (&x != this) is assumed.
- BOOST_ASSERT(this != &x);
- allocator_type &this_alloc = this->alloc();
- allocator_type &x_alloc = x.alloc();
- const bool propagate_alloc = allocator_traits_type::
- propagate_on_container_move_assignment::value;
- dtl::bool_<propagate_alloc> flag;
- const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
- //Resources can be transferred if both allocators are
- //going to be equal after this function (either propagated or already equal)
- if(propagate_alloc || allocators_equal){
- //Destroy objects but retain memory in case x reuses it in the future
- this->clear();
- //Move allocator if needed
- dtl::move_alloc(this_alloc, x_alloc, flag);
- //Nothrow swap
- this->swap_data(x);
- }
- //Else do a one by one move
- else{
- this->assign( x.begin(), x.end());
+ if (BOOST_LIKELY(this != &x)) {
+ allocator_type &this_alloc = this->alloc();
+ allocator_type &x_alloc = x.alloc();
+ const bool propagate_alloc = allocator_traits_type::
+ propagate_on_container_move_assignment::value;
+ dtl::bool_<propagate_alloc> flag;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ //Destroy objects but retain memory in case x reuses it in the future
+ this->clear();
+ //Move allocator if needed
+ dtl::move_alloc(this_alloc, x_alloc, flag);
+ //Nothrow swap
+ this->swap_data(x);
+ }
+ //Else do a one by one move
+ else{
+ this->assign( x.begin(), x.end());
+ }
}
return *this;
}
@@ -3490,9 +3490,9 @@ namespace boost {
template <class C, class T, class Allocator>
struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, Allocator> >
{
- typedef typename ::boost::container::allocator_traits
- <typename boost::container::basic_string<C, T, Allocator>::allocator_type>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ typedef typename boost::container::basic_string<C, T, Allocator>::allocator_type allocator_type;
+ typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value;
};
diff --git a/boost/container/vector.hpp b/boost/container/vector.hpp
index 010b599d6d..099a8781c2 100644
--- a/boost/container/vector.hpp
+++ b/boost/container/vector.hpp
@@ -501,6 +501,9 @@ struct vector_alloc_holder
BOOST_CONTAINER_FORCEINLINE void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW
{ BOOST_ASSERT( c <= stored_size_type(-1)); m_capacity = c; }
+ static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow()
+ { }
+
private:
void priv_first_allocation(size_type cap)
{
@@ -631,10 +634,13 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
(this->alloc(), boost::movelib::to_raw_pointer(holder.start()), n, boost::movelib::to_raw_pointer(this->start()));
}
+ static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow()
+ { allocator_type::on_capacity_overflow(); }
+
BOOST_CONTAINER_FORCEINLINE void priv_first_allocation(size_type cap)
{
if(cap > allocator_type::internal_capacity){
- throw_bad_alloc();
+ on_capacity_overflow();
}
}
@@ -648,20 +654,20 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
{
typedef typename real_allocator<value_type, OtherAllocator>::type other_allocator_type;
if(this->m_size > other_allocator_type::internal_capacity || x.m_size > allocator_type::internal_capacity){
- throw_bad_alloc();
+ on_capacity_overflow();
}
this->priv_deep_swap(x);
}
BOOST_CONTAINER_FORCEINLINE void swap_resources(vector_alloc_holder &) BOOST_NOEXCEPT_OR_NOTHROW
{ //Containers with version 0 allocators can't be moved without moving elements one by one
- throw_bad_alloc();
+ on_capacity_overflow();
}
BOOST_CONTAINER_FORCEINLINE void steal_resources(vector_alloc_holder &)
{ //Containers with version 0 allocators can't be moved without moving elements one by one
- throw_bad_alloc();
+ on_capacity_overflow();
}
BOOST_CONTAINER_FORCEINLINE allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
@@ -702,18 +708,6 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
struct growth_factor_60;
-template<class T, class Default>
-struct default_if_void
-{
- typedef T type;
-};
-
-template<class Default>
-struct default_if_void<void, Default>
-{
- typedef Default type;
-};
-
template<class Options, class AllocatorSizeType>
struct get_vector_opt
{
@@ -728,7 +722,6 @@ struct get_vector_opt<void, AllocatorSizeType>
typedef vector_opt<growth_factor_60, AllocatorSizeType> type;
};
-
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A vector is a sequence that supports random access to elements, constant
@@ -2340,7 +2333,7 @@ private:
template<class FwdIt, class Compare>
BOOST_CONTAINER_FORCEINLINE void priv_merge_in_new_buffer(FwdIt, size_type, Compare, version_0)
{
- throw_bad_alloc();
+ alloc_holder_t::on_capacity_overflow();
}
template<class FwdIt, class Compare, class Version>
@@ -2420,7 +2413,7 @@ private:
{
if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
this->capacity() < x.size()){
- throw_bad_alloc();
+ alloc_holder_t::on_capacity_overflow();
}
T* const this_start = this->priv_raw_begin();
T* const other_start = x.priv_raw_begin();
@@ -2472,7 +2465,7 @@ private:
{
if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
this->capacity() < x.size()){
- throw_bad_alloc();
+ alloc_holder_t::on_capacity_overflow();
}
T* const this_start = this->priv_raw_begin();
T* const other_start = x.priv_raw_begin();
@@ -2541,7 +2534,7 @@ private:
}
void priv_reserve_no_capacity(size_type, version_0)
- { throw_bad_alloc(); }
+ { alloc_holder_t::on_capacity_overflow(); }
dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy()
{
@@ -2640,10 +2633,10 @@ private:
( vector_iterator_get_ptr(p), 1, dtl::get_insert_value_proxy<T*, allocator_type>(::boost::forward<U>(x)));
}
- dtl::insert_copy_proxy<allocator_type, T*> priv_single_insert_proxy(const T &x)
+ BOOST_CONTAINER_FORCEINLINE dtl::insert_copy_proxy<allocator_type, T*> priv_single_insert_proxy(const T &x)
{ return dtl::insert_copy_proxy<allocator_type, T*> (x); }
- dtl::insert_move_proxy<allocator_type, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
+ BOOST_CONTAINER_FORCEINLINE dtl::insert_move_proxy<allocator_type, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
{ return dtl::insert_move_proxy<allocator_type, T*> (x); }
template <class U>
@@ -2744,7 +2737,7 @@ private:
iterator priv_forward_range_insert_no_capacity
(const pointer &pos, const size_type, const InsertionProxy , version_0)
{
- throw_bad_alloc();
+ alloc_holder_t::on_capacity_overflow();
return iterator(pos);
}
@@ -2844,7 +2837,7 @@ private:
if (n > remaining){
//This will trigger an error
- throw_bad_alloc();
+ alloc_holder_t::on_capacity_overflow();
}
this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy);
return this->end();
@@ -3420,9 +3413,9 @@ namespace boost {
template <class T, class Allocator, class Options>
struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator, Options> >
{
- typedef typename ::boost::container::allocator_traits
- <typename boost::container::real_allocator<T, Allocator>::type>::pointer pointer;
- static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ typedef typename boost::container::vector<T, Allocator, Options>::allocator_type allocator_type;
+ typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
::boost::has_trivial_destructor_after_move<pointer>::value;
};
diff --git a/boost/convert/base.hpp b/boost/convert/base.hpp
index d8a7948e7c..791dbe0d15 100644
--- a/boost/convert/base.hpp
+++ b/boost/convert/base.hpp
@@ -27,7 +27,7 @@ namespace boost { namespace cnv
operator()
#define BOOST_CNV_PARAM(param_name, param_type) \
- derived_type& operator()(boost::parameter::aux::tag<ARG::type::param_name, param_type>::type const& arg)
+ derived_type& operator()(boost::parameter::aux::tag<ARG::type::param_name, param_type const>::type const& arg)
template<typename derived_type>
struct boost::cnv::cnvbase
@@ -78,15 +78,14 @@ struct boost::cnv::cnvbase
BOOST_CNV_STRING_TO (string_type const& s, optional< dbl_type>& r) const { str_to_(s, r); }
BOOST_CNV_STRING_TO (string_type const& s, optional< ldbl_type>& r) const { str_to_(s, r); }
// Formatters
-// BOOST_CNV_PARAM (locale, std::locale const) { locale_ = arg[ARG:: locale]; return dncast(); }
- BOOST_CNV_PARAM (base, cnv::base const) { base_ = arg[ARG:: base]; return dncast(); }
- BOOST_CNV_PARAM (adjust, cnv::adjust const) { adjust_ = arg[ARG:: adjust]; return dncast(); }
- BOOST_CNV_PARAM (precision, int const) { precision_ = arg[ARG::precision]; return dncast(); }
- BOOST_CNV_PARAM (precision, int) { precision_ = arg[ARG::precision]; return dncast(); }
- BOOST_CNV_PARAM (uppercase, bool const) { uppercase_ = arg[ARG::uppercase]; return dncast(); }
- BOOST_CNV_PARAM (skipws, bool const) { skipws_ = arg[ARG:: skipws]; return dncast(); }
- BOOST_CNV_PARAM (width, int const) { width_ = arg[ARG:: width]; return dncast(); }
- BOOST_CNV_PARAM (fill, char const) { fill_ = arg[ARG:: fill]; return dncast(); }
+// BOOST_CNV_PARAM (locale, std::locale) { locale_ = arg[ARG:: locale]; return dncast(); }
+ BOOST_CNV_PARAM (base, cnv::base) { base_ = arg[ARG:: base]; return dncast(); }
+ BOOST_CNV_PARAM (adjust, cnv::adjust) { adjust_ = arg[ARG:: adjust]; return dncast(); }
+ BOOST_CNV_PARAM (precision, int) { precision_ = arg[ARG::precision]; return dncast(); }
+ BOOST_CNV_PARAM (uppercase, bool) { uppercase_ = arg[ARG::uppercase]; return dncast(); }
+ BOOST_CNV_PARAM (skipws, bool) { skipws_ = arg[ARG:: skipws]; return dncast(); }
+ BOOST_CNV_PARAM (width, int) { width_ = arg[ARG:: width]; return dncast(); }
+ BOOST_CNV_PARAM (fill, char) { fill_ = arg[ARG:: fill]; return dncast(); }
protected:
diff --git a/boost/convert/detail/range.hpp b/boost/convert/detail/range.hpp
index 82d105f949..4279a5911d 100644
--- a/boost/convert/detail/range.hpp
+++ b/boost/convert/detail/range.hpp
@@ -74,7 +74,7 @@ namespace boost { namespace cnv
range (T& r) : base_type(r.begin(), r.end()) {}
- iterator end () { return base_type::end_; }
+ iterator end () { return base_type::end_; }
const_iterator end () const { return base_type::end_; }
sentry_type sentry () const { return base_type::end_; }
std::size_t size () const { return base_type::end_ - base_type::begin_; }
diff --git a/boost/convert/stream.hpp b/boost/convert/stream.hpp
index ee95d6914b..17ad2b6ab6 100644
--- a/boost/convert/stream.hpp
+++ b/boost/convert/stream.hpp
@@ -19,7 +19,7 @@
#define BOOST_CNV_PARAM(PARAM_NAME, PARAM_TYPE) \
this_type& \
- operator()(boost::parameter::aux::tag<boost::cnv::parameter::type::PARAM_NAME, PARAM_TYPE>::type const& arg)
+ operator()(boost::parameter::aux::tag<boost::cnv::parameter::type::PARAM_NAME, PARAM_TYPE const>::type const& arg)
namespace boost { namespace cnv
{
@@ -87,24 +87,23 @@ struct boost::cnv::basic_stream : boost::noncopyable
this_type& operator() (manipulator_type m) { return (m(stream_), *this); }
this_type& operator() (std::locale const& l) { return (stream_.imbue(l), *this); }
- BOOST_CNV_PARAM(locale, std::locale const) { return (stream_.imbue(arg[cnv::parameter::locale]), *this); }
- BOOST_CNV_PARAM(precision, int const) { return (stream_.precision(arg[cnv::parameter::precision]), *this); }
- BOOST_CNV_PARAM(precision, int) { return (stream_.precision(arg[cnv::parameter::precision]), *this); }
- BOOST_CNV_PARAM(width, int const) { return (stream_.width(arg[cnv::parameter::width]), *this); }
- BOOST_CNV_PARAM(fill, char const) { return (stream_.fill(arg[cnv::parameter::fill]), *this); }
- BOOST_CNV_PARAM(uppercase, bool const)
+ BOOST_CNV_PARAM(locale, std::locale) { return (stream_.imbue(arg[cnv::parameter::locale]), *this); }
+ BOOST_CNV_PARAM(precision, int) { return (stream_.precision(arg[cnv::parameter::precision]), *this); }
+ BOOST_CNV_PARAM(width, int) { return (stream_.width(arg[cnv::parameter::width]), *this); }
+ BOOST_CNV_PARAM(fill, char) { return (stream_.fill(arg[cnv::parameter::fill]), *this); }
+ BOOST_CNV_PARAM(uppercase, bool)
{
bool uppercase = arg[cnv::parameter::uppercase];
uppercase ? (void) stream_.setf(std::ios::uppercase) : stream_.unsetf(std::ios::uppercase);
return *this;
}
- BOOST_CNV_PARAM(skipws, bool const)
+ BOOST_CNV_PARAM(skipws, bool)
{
bool skipws = arg[cnv::parameter::skipws];
skipws ? (void) stream_.setf(std::ios::skipws) : stream_.unsetf(std::ios::skipws);
return *this;
}
- BOOST_CNV_PARAM(adjust, boost::cnv::adjust const)
+ BOOST_CNV_PARAM(adjust, boost::cnv::adjust)
{
cnv::adjust adjust = arg[cnv::parameter::adjust];
@@ -114,7 +113,7 @@ struct boost::cnv::basic_stream : boost::noncopyable
return *this;
}
- BOOST_CNV_PARAM(base, boost::cnv::base const)
+ BOOST_CNV_PARAM(base, boost::cnv::base)
{
cnv::base base = arg[cnv::parameter::base];
@@ -125,7 +124,7 @@ struct boost::cnv::basic_stream : boost::noncopyable
return *this;
}
- BOOST_CNV_PARAM(notation, boost::cnv::notation const)
+ BOOST_CNV_PARAM(notation, boost::cnv::notation)
{
cnv::notation notation = arg[cnv::parameter::notation];
@@ -158,7 +157,7 @@ boost::cnv::basic_stream<char_type>::to_str(
if (!(stream_ << value_in).fail())
{
buffer_type* buf = stream_.rdbuf();
- obuffer_type* obuf = static_cast<obuffer_type*>(buf);
+ obuffer_type* obuf = reinterpret_cast<obuffer_type*>(buf);
char_type const* beg = obuf->pbase();
char_type const* end = obuf->pptr();
diff --git a/boost/convert/strtol.hpp b/boost/convert/strtol.hpp
index 37f503d375..a762bba345 100644
--- a/boost/convert/strtol.hpp
+++ b/boost/convert/strtol.hpp
@@ -158,23 +158,25 @@ template<typename string_type, typename out_type>
void
boost::cnv::strtol::str_to_i(cnv::range<string_type> range, boost::optional<out_type>& result_out) const
{
- typedef typename boost::make_unsigned<out_type>::type unsigned_type;
- typedef cnv::range<string_type> range_type;
- typedef typename range_type::iterator iterator;
+ using uint_type = unsigned int;
+ using unsigned_type = typename boost::make_unsigned<out_type>::type;
+ using range_type = cnv::range<string_type>;
+ using iterator = typename range_type::iterator;
iterator s = range.begin();
- unsigned int ch = *s;
+ uint_type ch = *s;
bool const is_negative = ch == '-' ? (ch = *++s, true) : ch == '+' ? (ch = *++s, false) : false;
bool const is_unsigned = boost::is_same<out_type, unsigned_type>::value;
- int base = int(base_);
+ uint_type base = uint_type(base_);
/**/ if (is_negative && is_unsigned) return;
else if ((base == 0 || base == 16) && ch == '0' && (*++s == 'x' || *s == 'X')) ++s, base = 16;
else if (base == 0) base = ch == '0' ? (++s, 8) : 10;
- unsigned_type const max = (std::numeric_limits<out_type>::max)() + (is_negative ? 1 : 0);
- unsigned_type const cutoff = max / base;
- unsigned int const cutlim = max % base;
+ unsigned_type const max = (std::numeric_limits<out_type>::max)();
+ unsigned_type const umax = max + (is_negative ? 1 : 0);
+ unsigned_type const cutoff = umax / base;
+ uint_type const cutlim = umax % base;
unsigned_type result = 0;
for (; s != range.sentry(); ++s)
diff --git a/boost/core/alloc_construct.hpp b/boost/core/alloc_construct.hpp
new file mode 100644
index 0000000000..7b87525449
--- /dev/null
+++ b/boost/core/alloc_construct.hpp
@@ -0,0 +1,245 @@
+/*
+Copyright 2019 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_CORE_ALLOC_CONSTRUCT_HPP
+#define BOOST_CORE_ALLOC_CONSTRUCT_HPP
+
+#include <boost/core/noinit_adaptor.hpp>
+
+namespace boost {
+
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+template<class A, class T>
+inline void
+alloc_destroy(A& a, T* p)
+{
+ std::allocator_traits<A>::destroy(a, p);
+}
+
+template<class A, class T>
+inline void
+alloc_destroy_n(A& a, T* p, std::size_t n)
+{
+ while (n > 0) {
+ std::allocator_traits<A>::destroy(a, p + --n);
+ }
+}
+#else
+template<class A, class T>
+inline void
+alloc_destroy(A&, T* p)
+{
+ p->~T();
+}
+
+template<class A, class T>
+inline void
+alloc_destroy_n(A&, T* p, std::size_t n)
+{
+ while (n > 0) {
+ p[--n].~T();
+ }
+}
+#endif
+
+namespace detail {
+
+template<class A, class T>
+class alloc_destroyer {
+public:
+ alloc_destroyer(A& a, T* p) BOOST_NOEXCEPT
+ : a_(a),
+ p_(p),
+ n_(0) { }
+
+ ~alloc_destroyer() {
+ boost::alloc_destroy_n(a_, p_, n_);
+ }
+
+ std::size_t& size() BOOST_NOEXCEPT {
+ return n_;
+ }
+
+private:
+ alloc_destroyer(const alloc_destroyer&);
+ alloc_destroyer& operator=(const alloc_destroyer&);
+
+ A& a_;
+ T* p_;
+ std::size_t n_;
+};
+
+} /* detail */
+
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+template<class A, class T>
+inline void
+alloc_construct(A& a, T* p)
+{
+ std::allocator_traits<A>::construct(a, p);
+}
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+template<class A, class T, class U, class... V>
+inline void
+alloc_construct(A& a, T* p, U&& u, V&&... v)
+{
+ std::allocator_traits<A>::construct(a, p, std::forward<U>(u),
+ std::forward<V>(v)...);
+}
+#else
+template<class A, class T, class U>
+inline void
+alloc_construct(A& a, T* p, U&& u)
+{
+ std::allocator_traits<A>::construct(a, p, std::forward<U>(u));
+}
+#endif
+#else
+template<class A, class T, class U>
+inline void
+alloc_construct(A& a, T* p, const U& u)
+{
+ std::allocator_traits<A>::construct(a, p, u);
+}
+
+template<class A, class T, class U>
+inline void
+alloc_construct(A& a, T* p, U& u)
+{
+ std::allocator_traits<A>::construct(a, p, u);
+}
+#endif
+
+template<class A, class T>
+inline void
+alloc_construct_n(A& a, T* p, std::size_t n)
+{
+ detail::alloc_destroyer<A, T> hold(a, p);
+ for (std::size_t& i = hold.size(); i < n; ++i) {
+ std::allocator_traits<A>::construct(a, p + i);
+ }
+ hold.size() = 0;
+}
+
+template<class A, class T>
+inline void
+alloc_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m)
+{
+ detail::alloc_destroyer<A, T> hold(a, p);
+ for (std::size_t& i = hold.size(); i < n; ++i) {
+ std::allocator_traits<A>::construct(a, p + i, l[i % m]);
+ }
+ hold.size() = 0;
+}
+
+template<class A, class T, class I>
+inline void
+alloc_construct_n(A& a, T* p, std::size_t n, I b)
+{
+ detail::alloc_destroyer<A, T> hold(a, p);
+ for (std::size_t& i = hold.size(); i < n; void(++i), void(++b)) {
+ std::allocator_traits<A>::construct(a, p + i, *b);
+ }
+ hold.size() = 0;
+}
+#else
+template<class A, class T>
+inline void
+alloc_construct(A&, T* p)
+{
+ ::new(static_cast<void*>(p)) T();
+}
+
+template<class A, class T>
+inline void
+alloc_construct(noinit_adaptor<A>&, T* p)
+{
+ ::new(static_cast<void*>(p)) T;
+}
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+template<class A, class T, class U, class... V>
+inline void
+alloc_construct(A&, T* p, U&& u, V&&... v)
+{
+ ::new(static_cast<void*>(p)) T(std::forward<U>(u), std::forward<V>(v)...);
+}
+#else
+template<class A, class T, class U>
+inline void
+alloc_construct(A& a, T* p, U&& u)
+{
+ ::new(static_cast<void*>(p)) T(std::forward<U>(u));
+}
+#endif
+#else
+template<class A, class T, class U>
+inline void
+alloc_construct(A&, T* p, const U& u)
+{
+ ::new(static_cast<void*>(p)) T(u);
+}
+
+template<class A, class T, class U>
+inline void
+alloc_construct(A&, T* p, U& u)
+{
+ ::new(static_cast<void*>(p)) T(u);
+}
+#endif
+
+template<class A, class T>
+inline void
+alloc_construct_n(A& a, T* p, std::size_t n)
+{
+ detail::alloc_destroyer<A, T> hold(a, p);
+ for (std::size_t& i = hold.size(); i < n; ++i) {
+ ::new(static_cast<void*>(p + i)) T();
+ }
+ hold.size() = 0;
+}
+
+template<class A, class T>
+inline void
+alloc_construct_n(noinit_adaptor<A>& a, T* p, std::size_t n)
+{
+ detail::alloc_destroyer<noinit_adaptor<A>, T> hold(a, p);
+ for (std::size_t& i = hold.size(); i < n; ++i) {
+ ::new(static_cast<void*>(p + i)) T;
+ }
+ hold.size() = 0;
+}
+
+template<class A, class T>
+inline void
+alloc_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m)
+{
+ detail::alloc_destroyer<A, T> hold(a, p);
+ for (std::size_t& i = hold.size(); i < n; ++i) {
+ ::new(static_cast<void*>(p + i)) T(l[i % m]);
+ }
+ hold.size() = 0;
+}
+
+template<class A, class T, class I>
+inline void
+alloc_construct_n(A& a, T* p, std::size_t n, I b)
+{
+ detail::alloc_destroyer<A, T> hold(a, p);
+ for (std::size_t& i = hold.size(); i < n; void(++i), void(++b)) {
+ ::new(static_cast<void*>(p + i)) T(*b);
+ }
+ hold.size() = 0;
+}
+#endif
+
+} /* boost */
+
+#endif
diff --git a/boost/core/default_allocator.hpp b/boost/core/default_allocator.hpp
new file mode 100644
index 0000000000..a202f66bee
--- /dev/null
+++ b/boost/core/default_allocator.hpp
@@ -0,0 +1,158 @@
+/*
+Copyright 2019 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_CORE_DEFAULT_ALLOCATOR_HPP
+#define BOOST_CORE_DEFAULT_ALLOCATOR_HPP
+
+#include <boost/config.hpp>
+#include <new>
+#include <climits>
+
+#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
+#define BOOST_CORE_NO_CXX11_ALLOCATOR
+#endif
+
+namespace boost {
+
+#if defined(BOOST_NO_EXCEPTIONS)
+void throw_exception(const std::exception&);
+#endif
+
+namespace default_ {
+
+struct true_type {
+ typedef bool value_type;
+ typedef true_type type;
+
+ BOOST_STATIC_CONSTANT(bool, value = true);
+
+ BOOST_CONSTEXPR operator bool() const BOOST_NOEXCEPT {
+ return true;
+ }
+
+ BOOST_CONSTEXPR bool operator()() const BOOST_NOEXCEPT {
+ return true;
+ }
+};
+
+template<class T>
+struct add_reference {
+ typedef T& type;
+};
+
+template<>
+struct add_reference<void> {
+ typedef void type;
+};
+
+template<>
+struct add_reference<const void> {
+ typedef const void type;
+};
+
+template<class T>
+struct default_allocator {
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef typename add_reference<T>::type reference;
+ typedef typename add_reference<const T>::type const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef true_type propagate_on_container_move_assignment;
+ typedef true_type is_always_equal;
+
+ template<class U>
+ struct rebind {
+ typedef default_allocator<U> other;
+ };
+
+#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
+ default_allocator() = default;
+#else
+ BOOST_CONSTEXPR default_allocator() BOOST_NOEXCEPT { }
+#endif
+
+ template<class U>
+ BOOST_CONSTEXPR default_allocator(const default_allocator<U>&)
+ BOOST_NOEXCEPT { }
+
+#if defined(PTRDIFF_MAX) && defined(SIZE_MAX)
+ BOOST_CONSTEXPR std::size_t max_size() const BOOST_NOEXCEPT {
+ return PTRDIFF_MAX < SIZE_MAX / sizeof(T)
+ ? PTRDIFF_MAX : SIZE_MAX / sizeof(T);
+ }
+#else
+ BOOST_CONSTEXPR std::size_t max_size() const BOOST_NOEXCEPT {
+ return ~static_cast<std::size_t>(0) / sizeof(T);
+ }
+#endif
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+ T* allocate(std::size_t n) {
+ if (n > max_size()) {
+ throw std::bad_alloc();
+ }
+ return static_cast<T*>(::operator new(sizeof(T) * n));
+ }
+
+ void deallocate(T* p, std::size_t) {
+ ::operator delete(p);
+ }
+#else
+ T* allocate(std::size_t n) {
+ if (n > max_size()) {
+ boost::throw_exception(std::bad_alloc());
+ }
+ void* p = ::operator new(sizeof(T) * n, std::nothrow);
+ if (!p) {
+ boost::throw_exception(std::bad_alloc());
+ }
+ return static_cast<T*>(p);
+ }
+
+ void deallocate(T* p, std::size_t) {
+ ::operator delete(p, std::nothrow);
+ }
+#endif
+
+#if defined(BOOST_NO_CXX11_ALLOCATOR) || defined(BOOST_CORE_NO_CXX11_ALLOCATOR)
+ template<class U, class V>
+ void construct(U* p, const V& v) {
+ ::new(p) U(v);
+ }
+
+ template<class U>
+ void destroy(U* p) {
+ p->~U();
+ }
+#endif
+};
+
+template<class T, class U>
+BOOST_CONSTEXPR inline bool
+operator==(const default_allocator<T>&,
+ const default_allocator<U>&) BOOST_NOEXCEPT
+{
+ return true;
+}
+
+template<class T, class U>
+BOOST_CONSTEXPR inline bool
+operator!=(const default_allocator<T>&,
+ const default_allocator<U>&) BOOST_NOEXCEPT
+{
+ return false;
+}
+
+} /* default_ */
+
+using default_::default_allocator;
+
+} /* boost */
+
+#endif
diff --git a/boost/core/empty_value.hpp b/boost/core/empty_value.hpp
index 9265f05d3a..7139b3e135 100644
--- a/boost/core/empty_value.hpp
+++ b/boost/core/empty_value.hpp
@@ -71,6 +71,10 @@ public:
template<class U>
empty_value(boost::empty_init_t, const U& value)
: value_(value) { }
+
+ template<class U>
+ empty_value(boost::empty_init_t, U& value)
+ : value_(value) { }
#endif
const T& get() const BOOST_NOEXCEPT {
@@ -115,6 +119,10 @@ public:
template<class U>
empty_value(boost::empty_init_t, const U& value)
: T(value) { }
+
+ template<class U>
+ empty_value(boost::empty_init_t, U& value)
+ : T(value) { }
#endif
const T& get() const BOOST_NOEXCEPT {
diff --git a/boost/core/first_scalar.hpp b/boost/core/first_scalar.hpp
new file mode 100644
index 0000000000..5373542e02
--- /dev/null
+++ b/boost/core/first_scalar.hpp
@@ -0,0 +1,45 @@
+/*
+Copyright 2019 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_CORE_FIRST_SCALAR_HPP
+#define BOOST_CORE_FIRST_SCALAR_HPP
+
+#include <boost/config.hpp>
+#include <cstddef>
+
+namespace boost {
+namespace detail {
+
+template<class T>
+struct make_scalar {
+ typedef T type;
+};
+
+template<class T, std::size_t N>
+struct make_scalar<T[N]> {
+ typedef typename make_scalar<T>::type type;
+};
+
+} /* detail */
+
+template<class T>
+BOOST_CONSTEXPR inline T*
+first_scalar(T* p) BOOST_NOEXCEPT
+{
+ return p;
+}
+
+template<class T, std::size_t N>
+BOOST_CONSTEXPR inline typename detail::make_scalar<T>::type*
+first_scalar(T (*p)[N]) BOOST_NOEXCEPT
+{
+ return boost::first_scalar(&(*p)[0]);
+}
+
+} /* boost */
+
+#endif
diff --git a/boost/core/lightweight_test.hpp b/boost/core/lightweight_test.hpp
index 45736cb733..0f8274d2e3 100644
--- a/boost/core/lightweight_test.hpp
+++ b/boost/core/lightweight_test.hpp
@@ -22,8 +22,8 @@
// http://www.boost.org/LICENSE_1_0.txt
//
-#include <boost/core/no_exceptions_support.hpp>
#include <boost/current_function.hpp>
+#include <boost/config.hpp>
#include <iostream>
#include <iterator>
#include <cstdlib>
@@ -379,18 +379,20 @@ inline int report_errors()
result.done();
int errors = result.errors();
+
if( errors == 0 )
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "No errors detected." << std::endl;
- return 0;
}
else
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< errors << " error" << (errors == 1? "": "s") << " detected." << std::endl;
- return 1;
}
+
+ // `return report_errors();` from main only supports 8 bit exit codes
+ return errors < 256? errors: 255;
}
} // namespace boost
diff --git a/boost/core/lightweight_test_trait.hpp b/boost/core/lightweight_test_trait.hpp
index 73770f4e15..26042c619d 100644
--- a/boost/core/lightweight_test_trait.hpp
+++ b/boost/core/lightweight_test_trait.hpp
@@ -13,6 +13,9 @@
//
// Copyright 2014 Peter Dimov
//
+// Copyright 2019 Glen Joseph Fernandes
+// (glenjofe@gmail.com)
+//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
@@ -20,6 +23,7 @@
#include <boost/core/lightweight_test.hpp>
#include <boost/core/typeinfo.hpp>
#include <boost/core/is_same.hpp>
+#include <boost/config.hpp>
namespace boost
{
@@ -27,6 +31,50 @@ namespace boost
namespace detail
{
+template<class, int = 0> struct test_print { };
+
+template<class T> inline std::ostream& operator<<(std::ostream& o, test_print<T, 2>)
+{
+ return o << boost::core::demangled_name(BOOST_CORE_TYPEID(T));
+}
+
+template<class T> inline std::ostream& operator<<(std::ostream& o, test_print<T, 1>)
+{
+ return o << test_print<T, 2>();
+}
+
+template<class T> inline std::ostream& operator<<(std::ostream& o, test_print<const T, 1>)
+{
+ return o << test_print<T, 2>() << " const";
+}
+
+template<class T> inline std::ostream& operator<<(std::ostream& o, test_print<volatile T, 1>)
+{
+ return o << test_print<T, 2>() << " volatile";
+}
+
+template<class T> inline std::ostream& operator<<(std::ostream& o, test_print<const volatile T, 1>)
+{
+ return o << test_print<T, 2>() << " const volatile";
+}
+
+template<class T> inline std::ostream& operator<<(std::ostream& o, test_print<T>)
+{
+ return o << test_print<T, 1>();
+}
+
+template<class T> inline std::ostream& operator<<(std::ostream& o, test_print<T&>)
+{
+ return o << test_print<T, 1>() << " &";
+}
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+template<class T> inline std::ostream& operator<<(std::ostream& o, test_print<T&&>)
+{
+ return o << test_print<T, 1>() << " &&";
+}
+#endif
+
template< class T > inline void test_trait_impl( char const * trait, void (*)( T ),
bool expected, char const * file, int line, char const * function )
{
@@ -64,8 +112,8 @@ template<class T1, class T2> inline void test_trait_same_impl( char const * type
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< file << "(" << line << "): test 'is_same<" << types << ">'"
<< " failed in function '" << function
- << "' ('" << boost::core::demangled_name( BOOST_CORE_TYPEID(T1) )
- << "' != '" << boost::core::demangled_name( BOOST_CORE_TYPEID(T2) ) << "')"
+ << "' ('" << test_print<T1>()
+ << "' != '" << test_print<T2>() << "')"
<< std::endl;
++test_results().errors();
diff --git a/boost/core/no_exceptions_support.hpp b/boost/core/no_exceptions_support.hpp
index e2453d084b..6fd76b241a 100644
--- a/boost/core/no_exceptions_support.hpp
+++ b/boost/core/no_exceptions_support.hpp
@@ -32,9 +32,21 @@
# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
# define BOOST_TRY { if ("")
# define BOOST_CATCH(x) else if (!"")
-# else
+# elif !defined(BOOST_MSVC) || BOOST_MSVC >= 1900
# define BOOST_TRY { if (true)
# define BOOST_CATCH(x) else if (false)
+# else
+ // warning C4127: conditional expression is constant
+# define BOOST_TRY { \
+ __pragma(warning(push)) \
+ __pragma(warning(disable: 4127)) \
+ if (true) \
+ __pragma(warning(pop))
+# define BOOST_CATCH(x) else \
+ __pragma(warning(push)) \
+ __pragma(warning(disable: 4127)) \
+ if (false) \
+ __pragma(warning(pop))
# endif
# define BOOST_RETHROW
# define BOOST_CATCH_END }
diff --git a/boost/core/noinit_adaptor.hpp b/boost/core/noinit_adaptor.hpp
new file mode 100644
index 0000000000..22c9aaba4e
--- /dev/null
+++ b/boost/core/noinit_adaptor.hpp
@@ -0,0 +1,112 @@
+/*
+Copyright 2019 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_CORE_NOINIT_ADAPTOR_HPP
+#define BOOST_CORE_NOINIT_ADAPTOR_HPP
+
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+#include <memory>
+#endif
+#include <new>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#include <utility>
+#endif
+
+namespace boost {
+
+template<class A>
+struct noinit_adaptor
+ : A {
+ template<class U>
+ struct rebind {
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+ typedef noinit_adaptor<typename std::allocator_traits<A>::template
+ rebind_alloc<U> > other;
+#else
+ typedef noinit_adaptor<typename A::template rebind<U>::other> other;
+#endif
+ };
+
+ noinit_adaptor()
+ : A() { }
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template<class U>
+ noinit_adaptor(U&& u) BOOST_NOEXCEPT
+ : A(std::forward<U>(u)) { }
+#else
+ template<class U>
+ noinit_adaptor(const U& u) BOOST_NOEXCEPT
+ : A(u) { }
+#endif
+
+ template<class U>
+ noinit_adaptor(const noinit_adaptor<U>& u) BOOST_NOEXCEPT
+ : A(static_cast<const U&>(u)) { }
+
+ template<class U>
+ void construct(U* p) {
+ ::new((void*)p) U;
+ }
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template<class U, class V, class... Args>
+ void construct(U* p, V&& v, Args&&... args) {
+ ::new((void*)p) U(std::forward<V>(v), std::forward<Args>(args)...);
+ }
+#else
+ template<class U, class V>
+ void construct(U* p, V&& v) {
+ ::new((void*)p) U(std::forward<V>(v));
+ }
+#endif
+#else
+ template<class U, class V>
+ void construct(U* p, const V& v) {
+ ::new((void*)p) U(v);
+ }
+
+ template<class U, class V>
+ void construct(U* p, V& v) {
+ ::new((void*)p) U(v);
+ }
+#endif
+
+ template<class U>
+ void destroy(U* p) {
+ p->~U();
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const noinit_adaptor<T>& lhs,
+ const noinit_adaptor<U>& rhs) BOOST_NOEXCEPT
+{
+ return static_cast<const T&>(lhs) == static_cast<const U&>(rhs);
+}
+
+template<class T, class U>
+inline bool
+operator!=(const noinit_adaptor<T>& lhs,
+ const noinit_adaptor<U>& rhs) BOOST_NOEXCEPT
+{
+ return !(lhs == rhs);
+}
+
+template<class A>
+inline noinit_adaptor<A>
+noinit_adapt(const A& a) BOOST_NOEXCEPT
+{
+ return noinit_adaptor<A>(a);
+}
+
+} /* boost */
+
+#endif
diff --git a/boost/core/typeinfo.hpp b/boost/core/typeinfo.hpp
index a272596a82..d33d29ba68 100644
--- a/boost/core/typeinfo.hpp
+++ b/boost/core/typeinfo.hpp
@@ -47,7 +47,7 @@ public:
bool operator==( typeinfo const& rhs ) const
{
-#if ( defined(_WIN32) || defined(__CYGWIN__) ) && defined(__GNUC__) && !defined(BOOST_DISABLE_CURRENT_FUNCTION)
+#if ( defined(_WIN32) || defined(__CYGWIN__) ) && ( defined(__GNUC__) || defined(__clang__) ) && !defined(BOOST_DISABLE_CURRENT_FUNCTION)
return lib_id_ == rhs.lib_id_? this == &rhs: std::strcmp( name_, rhs.name_ ) == 0;
@@ -65,7 +65,7 @@ public:
bool before( typeinfo const& rhs ) const
{
-#if ( defined(_WIN32) || defined(__CYGWIN__) ) && defined(__GNUC__) && !defined(BOOST_DISABLE_CURRENT_FUNCTION)
+#if ( defined(_WIN32) || defined(__CYGWIN__) ) && ( defined(__GNUC__) || defined(__clang__) ) && !defined(BOOST_DISABLE_CURRENT_FUNCTION)
return lib_id_ == rhs.lib_id_? std::less< typeinfo const* >()( this, &rhs ): std::strcmp( name_, rhs.name_ ) < 0;
diff --git a/boost/core/uncaught_exceptions.hpp b/boost/core/uncaught_exceptions.hpp
index 29b1c7ae79..27e2491bda 100644
--- a/boost/core/uncaught_exceptions.hpp
+++ b/boost/core/uncaught_exceptions.hpp
@@ -9,7 +9,7 @@
* \author Andrey Semashev
* \date 2018-11-10
*
- * \brief This header provides an `uncaught_exception` function implementation, which was introduced in C++17.
+ * \brief This header provides an `uncaught_exceptions` function implementation, which was introduced in C++17.
*
* The code in this file is based on the implementation by Evgeny Panasyuk:
*
@@ -56,10 +56,15 @@
// On Linux with clang and libc++ and on OS X, there is a version of cxxabi.h from libc++abi that doesn't declare __cxa_get_globals, but provides __cxa_uncaught_exceptions.
// The function only appeared in version _LIBCPPABI_VERSION >= 1002 of the library. Unfortunately, there are linking errors about undefined reference to __cxa_uncaught_exceptions
// on Ubuntu Trusty and OS X, so we avoid using it and forward-declare __cxa_get_globals instead.
+// On QNX SDP 7.0 (QCC 5.4.0), there are multiple cxxabi.h, one from glibcxx from gcc and another from libc++abi from LLVM. Which one is included will be determined by the qcc
+// command line arguments (-V and/or -Y; http://www.qnx.com/developers/docs/7.0.0/#com.qnx.doc.neutrino.utilities/topic/q/qcc.html). The LLVM libc++abi is missing the declaration
+// of __cxa_get_globals but it is also patched by QNX developers to not define _LIBCPPABI_VERSION. Older QNX SDP versions, up to and including 6.6, don't provide LLVM and libc++abi.
+// See https://github.com/boostorg/core/issues/59.
#if !defined(__FreeBSD__) && \
( \
(defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407) || \
defined(__OpenBSD__) || \
+ (defined(__QNXNTO__) && !defined(__GLIBCXX__) && !defined(__GLIBCPP__)) || \
defined(_LIBCPPABI_VERSION) \
)
namespace __cxxabiv1 {
diff --git a/boost/date_time/gregorian/greg_date.hpp b/boost/date_time/gregorian/greg_date.hpp
index 4f56bedf1a..448ea90fa3 100644
--- a/boost/date_time/gregorian/greg_date.hpp
+++ b/boost/date_time/gregorian/greg_date.hpp
@@ -120,7 +120,7 @@ namespace gregorian {
date end_of_month() const
{
ymd_type ymd = year_month_day();
- short eom_day = gregorian_calendar::end_of_month_day(ymd.year, ymd.month);
+ unsigned short eom_day = gregorian_calendar::end_of_month_day(ymd.year, ymd.month);
return date(ymd.year, ymd.month, eom_day);
}
diff --git a/boost/detail/interlocked.hpp b/boost/detail/interlocked.hpp
index b746cccff1..8084857bbe 100644
--- a/boost/detail/interlocked.hpp
+++ b/boost/detail/interlocked.hpp
@@ -5,7 +5,7 @@
// boost/detail/interlocked.hpp
//
// Copyright 2005 Peter Dimov
-// Copyright 2018 Andrey Semashev
+// Copyright 2018, 2019 Andrey Semashev
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -31,9 +31,10 @@
// MinGW-w64 provides intrin.h for both 32 and 64-bit targets.
# define BOOST_INTERLOCKED_HAS_INTRIN_H
-#elif defined( __CYGWIN__ ) && defined( __LP64__ )
+#elif defined( __CYGWIN__ )
-// We have to use intrin.h on Cygwin 64
+// Cygwin and Cygwin64 provide intrin.h. On Cygwin64 we have to use intrin.h because it's an LP64 target,
+// where long is 64-bit and therefore _Interlocked* functions have different signatures.
# define BOOST_INTERLOCKED_HAS_INTRIN_H
// Intel C++ on Windows on VC10+ stdlib
@@ -48,39 +49,62 @@
#endif
+#if !defined(__LP64__)
+#define BOOST_INTERLOCKED_LONG32 long
+#else
+#define BOOST_INTERLOCKED_LONG32 int
+#endif
+
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
-# define BOOST_INTERLOCKED_INCREMENT InterlockedIncrement
-# define BOOST_INTERLOCKED_DECREMENT InterlockedDecrement
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange
-# define BOOST_INTERLOCKED_EXCHANGE InterlockedExchange
-# define BOOST_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER InterlockedCompareExchangePointer
-# define BOOST_INTERLOCKED_EXCHANGE_POINTER InterlockedExchangePointer
+# define BOOST_INTERLOCKED_INCREMENT(dest) \
+ InterlockedIncrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_DECREMENT(dest) \
+ InterlockedDecrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) \
+ InterlockedCompareExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange), (BOOST_INTERLOCKED_LONG32)(compare))
+# define BOOST_INTERLOCKED_EXCHANGE(dest, exchange) \
+ InterlockedExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange))
+# define BOOST_INTERLOCKED_EXCHANGE_ADD(dest, add) \
+ InterlockedExchangeAdd((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(add))
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) \
+ InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare))
+# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) \
+ InterlockedExchangePointer((void**)(dest), (void*)(exchange))
#elif defined( BOOST_USE_INTRIN_H ) || defined( BOOST_INTERLOCKED_HAS_INTRIN_H )
#include <intrin.h>
-# define BOOST_INTERLOCKED_INCREMENT _InterlockedIncrement
-# define BOOST_INTERLOCKED_DECREMENT _InterlockedDecrement
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange
-# define BOOST_INTERLOCKED_EXCHANGE _InterlockedExchange
-# define BOOST_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd
-
-# if defined(_M_IA64) || defined(_M_AMD64) || defined(__x86_64__) || defined(__x86_64)
-
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER _InterlockedCompareExchangePointer
-# define BOOST_INTERLOCKED_EXCHANGE_POINTER _InterlockedExchangePointer
+# define BOOST_INTERLOCKED_INCREMENT(dest) \
+ _InterlockedIncrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_DECREMENT(dest) \
+ _InterlockedDecrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) \
+ _InterlockedCompareExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange), (BOOST_INTERLOCKED_LONG32)(compare))
+# define BOOST_INTERLOCKED_EXCHANGE(dest, exchange) \
+ _InterlockedExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange))
+# define BOOST_INTERLOCKED_EXCHANGE_ADD(dest, add) \
+ _InterlockedExchangeAdd((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(add))
+
+// Note: Though MSVC-12 defines _InterlockedCompareExchangePointer and _InterlockedExchangePointer in intrin.h, the latter
+// is actually broken as it conflicts with winnt.h from Windows SDK 8.1.
+# if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
+ (defined(_M_IA64) || defined(_M_AMD64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_ARM64))
+
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) \
+ _InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare))
+# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) \
+ _InterlockedExchangePointer((void**)(dest), (void*)(exchange))
# else
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest,exchange,compare) \
- ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((long volatile*)(dest),(long)(exchange),(long)(compare)))
-# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest,exchange) \
- ((void*)BOOST_INTERLOCKED_EXCHANGE((long volatile*)(dest),(long)(exchange)))
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) \
+ ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange), (BOOST_INTERLOCKED_LONG32)(compare)))
+# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) \
+ ((void*)BOOST_INTERLOCKED_EXCHANGE((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange)))
# endif
@@ -88,40 +112,50 @@
#if _WIN32_WCE >= 0x600
-extern "C" long __cdecl _InterlockedIncrement( long volatile * );
-extern "C" long __cdecl _InterlockedDecrement( long volatile * );
-extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long );
-extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
-extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long );
-
-# define BOOST_INTERLOCKED_INCREMENT _InterlockedIncrement
-# define BOOST_INTERLOCKED_DECREMENT _InterlockedDecrement
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange
-# define BOOST_INTERLOCKED_EXCHANGE _InterlockedExchange
-# define BOOST_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd
+extern "C" BOOST_INTERLOCKED_LONG32 __cdecl _InterlockedIncrement( BOOST_INTERLOCKED_LONG32 volatile * );
+extern "C" BOOST_INTERLOCKED_LONG32 __cdecl _InterlockedDecrement( BOOST_INTERLOCKED_LONG32 volatile * );
+extern "C" BOOST_INTERLOCKED_LONG32 __cdecl _InterlockedCompareExchange( BOOST_INTERLOCKED_LONG32 volatile *, BOOST_INTERLOCKED_LONG32, BOOST_INTERLOCKED_LONG32 );
+extern "C" BOOST_INTERLOCKED_LONG32 __cdecl _InterlockedExchange( BOOST_INTERLOCKED_LONG32 volatile *, BOOST_INTERLOCKED_LONG32 );
+extern "C" BOOST_INTERLOCKED_LONG32 __cdecl _InterlockedExchangeAdd( BOOST_INTERLOCKED_LONG32 volatile *, BOOST_INTERLOCKED_LONG32 );
+
+# define BOOST_INTERLOCKED_INCREMENT(dest) \
+ _InterlockedIncrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_DECREMENT(dest) \
+ _InterlockedDecrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) \
+ _InterlockedCompareExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange), (BOOST_INTERLOCKED_LONG32)(compare))
+# define BOOST_INTERLOCKED_EXCHANGE(dest, exchange) \
+ _InterlockedExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange))
+# define BOOST_INTERLOCKED_EXCHANGE_ADD(dest, add) \
+ _InterlockedExchangeAdd((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(add))
#else // _WIN32_WCE >= 0x600
// under Windows CE we still have old-style Interlocked* functions
-extern "C" long __cdecl InterlockedIncrement( long * );
-extern "C" long __cdecl InterlockedDecrement( long * );
-extern "C" long __cdecl InterlockedCompareExchange( long *, long, long );
-extern "C" long __cdecl InterlockedExchange( long *, long );
-extern "C" long __cdecl InterlockedExchangeAdd( long *, long );
-
-# define BOOST_INTERLOCKED_INCREMENT InterlockedIncrement
-# define BOOST_INTERLOCKED_DECREMENT InterlockedDecrement
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange
-# define BOOST_INTERLOCKED_EXCHANGE InterlockedExchange
-# define BOOST_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd
+extern "C" BOOST_INTERLOCKED_LONG32 __cdecl InterlockedIncrement( BOOST_INTERLOCKED_LONG32 * );
+extern "C" BOOST_INTERLOCKED_LONG32 __cdecl InterlockedDecrement( BOOST_INTERLOCKED_LONG32 * );
+extern "C" BOOST_INTERLOCKED_LONG32 __cdecl InterlockedCompareExchange( BOOST_INTERLOCKED_LONG32 *, BOOST_INTERLOCKED_LONG32, BOOST_INTERLOCKED_LONG32 );
+extern "C" BOOST_INTERLOCKED_LONG32 __cdecl InterlockedExchange( BOOST_INTERLOCKED_LONG32 *, BOOST_INTERLOCKED_LONG32 );
+extern "C" BOOST_INTERLOCKED_LONG32 __cdecl InterlockedExchangeAdd( BOOST_INTERLOCKED_LONG32 *, BOOST_INTERLOCKED_LONG32 );
+
+# define BOOST_INTERLOCKED_INCREMENT(dest) \
+ InterlockedIncrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_DECREMENT(dest) \
+ InterlockedDecrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) \
+ InterlockedCompareExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange), (BOOST_INTERLOCKED_LONG32)(compare))
+# define BOOST_INTERLOCKED_EXCHANGE(dest, exchange) \
+ InterlockedExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange))
+# define BOOST_INTERLOCKED_EXCHANGE_ADD(dest, add) \
+ InterlockedExchangeAdd((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(add))
#endif // _WIN32_WCE >= 0x600
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest,exchange,compare) \
- ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)(dest),(long)(exchange),(long)(compare)))
-# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest,exchange) \
- ((void*)BOOST_INTERLOCKED_EXCHANGE((long*)(dest),(long)(exchange)))
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) \
+ ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange), (BOOST_INTERLOCKED_LONG32)(compare)))
+# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) \
+ ((void*)BOOST_INTERLOCKED_EXCHANGE((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange)))
#elif defined( BOOST_MSVC ) || defined( BOOST_INTEL_WIN )
@@ -131,13 +165,11 @@ extern "C" long __cdecl InterlockedExchangeAdd( long *, long );
# define BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL __cdecl
# endif
-extern "C" long BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedIncrement( long volatile * );
-extern "C" long BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedDecrement( long volatile * );
-extern "C" long BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedCompareExchange( long volatile *, long, long );
-extern "C" long BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedExchange( long volatile *, long );
-extern "C" long BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedExchangeAdd( long volatile *, long );
-
-# undef BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL
+extern "C" BOOST_INTERLOCKED_LONG32 BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedIncrement( BOOST_INTERLOCKED_LONG32 volatile * );
+extern "C" BOOST_INTERLOCKED_LONG32 BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedDecrement( BOOST_INTERLOCKED_LONG32 volatile * );
+extern "C" BOOST_INTERLOCKED_LONG32 BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedCompareExchange( BOOST_INTERLOCKED_LONG32 volatile *, BOOST_INTERLOCKED_LONG32, BOOST_INTERLOCKED_LONG32 );
+extern "C" BOOST_INTERLOCKED_LONG32 BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedExchange( BOOST_INTERLOCKED_LONG32 volatile *, BOOST_INTERLOCKED_LONG32 );
+extern "C" BOOST_INTERLOCKED_LONG32 BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedExchangeAdd( BOOST_INTERLOCKED_LONG32 volatile *, BOOST_INTERLOCKED_LONG32 );
# if defined( BOOST_MSVC ) && BOOST_MSVC >= 1310
# pragma intrinsic( _InterlockedIncrement )
@@ -147,30 +179,44 @@ extern "C" long BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedExchangeAdd(
# pragma intrinsic( _InterlockedExchangeAdd )
# endif
-# if defined(_M_IA64) || defined(_M_AMD64)
+# if defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM64)
+
+extern "C" void* BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedCompareExchangePointer( void* volatile *, void*, void* );
+extern "C" void* BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL _InterlockedExchangePointer( void* volatile *, void* );
-extern "C" void* __cdecl _InterlockedCompareExchangePointer( void* volatile *, void*, void* );
-extern "C" void* __cdecl _InterlockedExchangePointer( void* volatile *, void* );
+# if defined( BOOST_MSVC ) && BOOST_MSVC >= 1310
+# pragma intrinsic( _InterlockedCompareExchangePointer )
+# pragma intrinsic( _InterlockedExchangePointer )
+# endif
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER _InterlockedCompareExchangePointer
-# define BOOST_INTERLOCKED_EXCHANGE_POINTER _InterlockedExchangePointer
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) \
+ _InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare))
+# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) \
+ _InterlockedExchangePointer((void**)(dest), (void*)(exchange))
# else
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest,exchange,compare) \
- ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((long volatile*)(dest),(long)(exchange),(long)(compare)))
-# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest,exchange) \
- ((void*)BOOST_INTERLOCKED_EXCHANGE((long volatile*)(dest),(long)(exchange)))
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) \
+ ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange), (BOOST_INTERLOCKED_LONG32)(compare)))
+# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) \
+ ((void*)BOOST_INTERLOCKED_EXCHANGE((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange)))
# endif
-# define BOOST_INTERLOCKED_INCREMENT _InterlockedIncrement
-# define BOOST_INTERLOCKED_DECREMENT _InterlockedDecrement
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange
-# define BOOST_INTERLOCKED_EXCHANGE _InterlockedExchange
-# define BOOST_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd
+# undef BOOST_INTERLOCKED_CLRCALL_PURE_OR_CDECL
+
+# define BOOST_INTERLOCKED_INCREMENT(dest) \
+ _InterlockedIncrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_DECREMENT(dest) \
+ _InterlockedDecrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) \
+ _InterlockedCompareExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange), (BOOST_INTERLOCKED_LONG32)(compare))
+# define BOOST_INTERLOCKED_EXCHANGE(dest, exchange) \
+ _InterlockedExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange))
+# define BOOST_INTERLOCKED_EXCHANGE_ADD(dest, add) \
+ _InterlockedExchangeAdd((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(add))
-#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
+#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
#define BOOST_INTERLOCKED_IMPORT __declspec(dllimport)
@@ -180,13 +226,13 @@ namespace boost
namespace detail
{
-extern "C" BOOST_INTERLOCKED_IMPORT long __stdcall InterlockedIncrement( long volatile * );
-extern "C" BOOST_INTERLOCKED_IMPORT long __stdcall InterlockedDecrement( long volatile * );
-extern "C" BOOST_INTERLOCKED_IMPORT long __stdcall InterlockedCompareExchange( long volatile *, long, long );
-extern "C" BOOST_INTERLOCKED_IMPORT long __stdcall InterlockedExchange( long volatile *, long );
-extern "C" BOOST_INTERLOCKED_IMPORT long __stdcall InterlockedExchangeAdd( long volatile *, long );
+extern "C" BOOST_INTERLOCKED_IMPORT BOOST_INTERLOCKED_LONG32 __stdcall InterlockedIncrement( BOOST_INTERLOCKED_LONG32 volatile * );
+extern "C" BOOST_INTERLOCKED_IMPORT BOOST_INTERLOCKED_LONG32 __stdcall InterlockedDecrement( BOOST_INTERLOCKED_LONG32 volatile * );
+extern "C" BOOST_INTERLOCKED_IMPORT BOOST_INTERLOCKED_LONG32 __stdcall InterlockedCompareExchange( BOOST_INTERLOCKED_LONG32 volatile *, BOOST_INTERLOCKED_LONG32, BOOST_INTERLOCKED_LONG32 );
+extern "C" BOOST_INTERLOCKED_IMPORT BOOST_INTERLOCKED_LONG32 __stdcall InterlockedExchange( BOOST_INTERLOCKED_LONG32 volatile *, BOOST_INTERLOCKED_LONG32 );
+extern "C" BOOST_INTERLOCKED_IMPORT BOOST_INTERLOCKED_LONG32 __stdcall InterlockedExchangeAdd( BOOST_INTERLOCKED_LONG32 volatile *, BOOST_INTERLOCKED_LONG32 );
-# if defined(_M_IA64) || defined(_M_AMD64)
+# if defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM64)
extern "C" BOOST_INTERLOCKED_IMPORT void* __stdcall InterlockedCompareExchangePointer( void* volatile *, void*, void* );
extern "C" BOOST_INTERLOCKED_IMPORT void* __stdcall InterlockedExchangePointer( void* volatile *, void* );
# endif
@@ -195,20 +241,27 @@ extern "C" BOOST_INTERLOCKED_IMPORT void* __stdcall InterlockedExchangePointer(
} // namespace boost
-# define BOOST_INTERLOCKED_INCREMENT ::boost::detail::InterlockedIncrement
-# define BOOST_INTERLOCKED_DECREMENT ::boost::detail::InterlockedDecrement
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE ::boost::detail::InterlockedCompareExchange
-# define BOOST_INTERLOCKED_EXCHANGE ::boost::detail::InterlockedExchange
-# define BOOST_INTERLOCKED_EXCHANGE_ADD ::boost::detail::InterlockedExchangeAdd
-
-# if defined(_M_IA64) || defined(_M_AMD64)
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER ::boost::detail::InterlockedCompareExchangePointer
-# define BOOST_INTERLOCKED_EXCHANGE_POINTER ::boost::detail::InterlockedExchangePointer
+# define BOOST_INTERLOCKED_INCREMENT(dest) \
+ ::boost::detail::InterlockedIncrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_DECREMENT(dest) \
+ ::boost::detail::InterlockedDecrement((BOOST_INTERLOCKED_LONG32*)(dest))
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) \
+ ::boost::detail::InterlockedCompareExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange), (BOOST_INTERLOCKED_LONG32)(compare))
+# define BOOST_INTERLOCKED_EXCHANGE(dest, exchange) \
+ ::boost::detail::InterlockedExchange((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(exchange))
+# define BOOST_INTERLOCKED_EXCHANGE_ADD(dest, add) \
+ ::boost::detail::InterlockedExchangeAdd((BOOST_INTERLOCKED_LONG32*)(dest), (BOOST_INTERLOCKED_LONG32)(add))
+
+# if defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM64)
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) \
+ ::boost::detail::InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare))
+# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) \
+ ::boost::detail::InterlockedExchangePointer((void**)(dest), (void*)(exchange))
# else
-# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest,exchange,compare) \
- ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((long volatile*)(dest),(long)(exchange),(long)(compare)))
-# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest,exchange) \
- ((void*)BOOST_INTERLOCKED_EXCHANGE((long volatile*)(dest),(long)(exchange)))
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) \
+ ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((BOOST_INTERLOCKED_LONG32 volatile*)(dest),(BOOST_INTERLOCKED_LONG32)(exchange),(BOOST_INTERLOCKED_LONG32)(compare)))
+# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) \
+ ((void*)BOOST_INTERLOCKED_EXCHANGE((BOOST_INTERLOCKED_LONG32*)(dest),(BOOST_INTERLOCKED_LONG32)(exchange)))
# endif
#else
diff --git a/boost/detail/sp_typeinfo.hpp b/boost/detail/sp_typeinfo.hpp
index 4e4de55b05..bec228f57d 100644
--- a/boost/detail/sp_typeinfo.hpp
+++ b/boost/detail/sp_typeinfo.hpp
@@ -18,6 +18,9 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/core/typeinfo.hpp>
+#include <boost/config/header_deprecated.hpp>
+
+BOOST_HEADER_DEPRECATED( "<boost/core/typeinfo.hpp>" )
namespace boost
{
diff --git a/boost/dynamic_bitset/detail/dynamic_bitset.hpp b/boost/dynamic_bitset/detail/dynamic_bitset.hpp
index 377d73f829..fb2343a956 100644
--- a/boost/dynamic_bitset/detail/dynamic_bitset.hpp
+++ b/boost/dynamic_bitset/detail/dynamic_bitset.hpp
@@ -5,6 +5,7 @@
// Copyright (c) 2014 Glen Joseph Fernandes
// (glenjofe@gmail.com)
// Copyright (c) 2018 Evgeny Shulgin
+// Copyright (c) 2019 Andrey Semashev
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -85,126 +86,129 @@ namespace boost {
struct count_table<false> { /* no table */ };
- const unsigned int table_width = 8;
- template <bool b>
- const byte_type count_table<b>::table[] =
- {
- // Automatically generated by GPTableGen.exe v.1.0
- //
- 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
- };
-
-
- // overload for access by bytes
- //
-
- template <typename Iterator>
- inline std::size_t do_count(Iterator first, std::size_t length,
- int /*dummy param*/,
- value_to_type<access_by_bytes>* )
- {
- std::size_t num = 0;
- if (length)
- {
- const byte_type * p = object_representation(&*first);
- length *= sizeof(*first);
-
- do {
- num += count_table<>::table[*p];
- ++p;
- --length;
-
- } while (length);
- }
-
- return num;
- }
-
-
- // Some platforms have fast popcount operation, that allow us to implement
- // counting bits much more efficiently
- //
- template <typename ValueType>
- BOOST_FORCEINLINE std::size_t popcount(ValueType value) BOOST_NOEXCEPT
- {
- std::size_t num = 0;
- while (value) {
- num += count_table<>::table[value & ((1u<<table_width) - 1)];
- value >>= table_width;
- }
- return num;
- }
+ const unsigned int table_width = 8;
+ template <bool b>
+ const byte_type count_table<b>::table[] =
+ {
+ // Automatically generated by GPTableGen.exe v.1.0
+ //
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+ };
-#if ((defined(BOOST_MSVC) && (BOOST_MSVC >= 1600)) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
-/*
- per https://github.com/boostorg/dynamic_bitset/issues/33
- this code does not support older cpus properly...
- it needs to check for cpuid support to avoid undefined behavior
-
- template <>
- BOOST_FORCEINLINE std::size_t popcount<unsigned short>(unsigned short value) BOOST_NOEXCEPT
- {
- return static_cast<std::size_t>(__popcnt16(value));
- }
-
- template <>
- BOOST_FORCEINLINE std::size_t popcount<unsigned int>(unsigned int value) BOOST_NOEXCEPT
- {
- return static_cast<std::size_t>(__popcnt(value));
- }
-
-#ifdef _M_X64
- template <>
- BOOST_FORCEINLINE std::size_t popcount<unsigned __int64>(unsigned __int64 value) BOOST_NOEXCEPT
- {
- return static_cast<std::size_t>(__popcnt64(value));
- }
+ // Some platforms have fast popcount operation, that allow us to implement
+ // counting bits much more efficiently
+ //
+ template <typename ValueType>
+ BOOST_FORCEINLINE std::size_t popcount(ValueType value) BOOST_NOEXCEPT
+ {
+ std::size_t num = 0u;
+ while (value) {
+ num += count_table<>::table[value & ((1u<<table_width) - 1)];
+ value >>= table_width;
+ }
+ return num;
+ }
+
+#if (((defined(BOOST_MSVC) && (BOOST_MSVC >= 1600)) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))) \
+ && (defined(__POPCNT__) || defined(__AVX__))
+
+ template <>
+ BOOST_FORCEINLINE std::size_t popcount<unsigned short>(unsigned short value) BOOST_NOEXCEPT
+ {
+ return static_cast<std::size_t>(__popcnt16(value));
+ }
+
+ template <>
+ BOOST_FORCEINLINE std::size_t popcount<unsigned int>(unsigned int value) BOOST_NOEXCEPT
+ {
+ return static_cast<std::size_t>(__popcnt(value));
+ }
+
+ template <>
+ BOOST_FORCEINLINE std::size_t popcount<unsigned __int64>(unsigned __int64 value) BOOST_NOEXCEPT
+ {
+#if defined(_M_X64)
+ return static_cast<std::size_t>(__popcnt64(value));
+#else
+ return static_cast<std::size_t>(__popcnt(static_cast< unsigned int >(value))) + static_cast<std::size_t>(__popcnt(static_cast< unsigned int >(value >> 32)));
#endif
- */
+ }
#elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
- template <>
- BOOST_FORCEINLINE std::size_t popcount<unsigned int>(unsigned int value) BOOST_NOEXCEPT
- {
- return __builtin_popcount(value);
- }
-
- template <>
- BOOST_FORCEINLINE std::size_t popcount<unsigned long>(unsigned long value) BOOST_NOEXCEPT
- {
- return __builtin_popcountl(value);
- }
-
- template <>
- BOOST_FORCEINLINE std::size_t popcount<boost::ulong_long_type>(boost::ulong_long_type value) BOOST_NOEXCEPT
- {
- return __builtin_popcountll(value);
- }
+
+ // Note: gcc builtins are implemented by compiler runtime when the target CPU may not support the necessary instructions
+ template <>
+ BOOST_FORCEINLINE std::size_t popcount<unsigned short>(unsigned short value) BOOST_NOEXCEPT
+ {
+ return static_cast<unsigned int>(__builtin_popcount(static_cast<unsigned int>(value)));
+ }
+
+ template <>
+ BOOST_FORCEINLINE std::size_t popcount<unsigned int>(unsigned int value) BOOST_NOEXCEPT
+ {
+ return static_cast<unsigned int>(__builtin_popcount(value));
+ }
+
+ template <>
+ BOOST_FORCEINLINE std::size_t popcount<unsigned long>(unsigned long value) BOOST_NOEXCEPT
+ {
+ return static_cast<unsigned int>(__builtin_popcountl(value));
+ }
+
+ template <>
+ BOOST_FORCEINLINE std::size_t popcount<boost::ulong_long_type>(boost::ulong_long_type value) BOOST_NOEXCEPT
+ {
+ return static_cast<unsigned int>(__builtin_popcountll(value));
+ }
+
#endif
- // overload for access by blocks
- //
- template <typename Iterator, typename ValueType>
- inline std::size_t do_count(Iterator first, std::size_t length, ValueType,
- value_to_type<access_by_blocks>*)
- {
- std::size_t num = 0;
- while (length){
- num += popcount<ValueType>(*first);
- ++first;
- --length;
- }
-
- return num;
- }
+ // overload for access by blocks
+ //
+ template <typename Iterator, typename ValueType>
+ inline std::size_t do_count(Iterator first, std::size_t length, ValueType,
+ value_to_type<access_by_blocks>*)
+ {
+ std::size_t num1 = 0u, num2 = 0u;
+ while (length >= 2u) {
+ num1 += popcount<ValueType>(*first);
+ ++first;
+ num2 += popcount<ValueType>(*first);
+ ++first;
+ length -= 2u;
+ }
+
+ if (length > 0u)
+ num1 += popcount<ValueType>(*first);
+
+ return num1 + num2;
+ }
+
+ // overload for access by bytes
+ //
+ template <typename Iterator>
+ inline std::size_t do_count(Iterator first, std::size_t length,
+ int /*dummy param*/,
+ value_to_type<access_by_bytes>*)
+ {
+ if (length > 0u) {
+ const byte_type* p = object_representation(&*first);
+ length *= sizeof(*first);
+
+ return do_count(p, length, static_cast<byte_type>(0u),
+ static_cast< value_to_type<access_by_blocks>* >(0));
+ }
+
+ return 0u;
+ }
// -------------------------------------------------------
diff --git a/boost/dynamic_bitset/dynamic_bitset.hpp b/boost/dynamic_bitset/dynamic_bitset.hpp
index a128a69845..f224051b3b 100644
--- a/boost/dynamic_bitset/dynamic_bitset.hpp
+++ b/boost/dynamic_bitset/dynamic_bitset.hpp
@@ -50,6 +50,7 @@
#include "boost/utility/addressof.hpp"
#include "boost/detail/no_exceptions_support.hpp"
#include "boost/throw_exception.hpp"
+#include "boost/functional/hash/hash.hpp"
namespace boost {
@@ -127,8 +128,10 @@ public:
typedef bool const_reference;
// constructors, etc.
+ dynamic_bitset() : m_num_bits(0) {}
+
explicit
- dynamic_bitset(const Allocator& alloc = Allocator());
+ dynamic_bitset(const Allocator& alloc);
explicit
dynamic_bitset(size_type num_bits, unsigned long value = 0,
@@ -354,7 +357,8 @@ public:
template <typename B, typename A, typename stringT>
friend void to_string_helper(const dynamic_bitset<B, A> & b, stringT & s, bool dump_all);
-
+ template <typename B, typename A>
+ friend std::size_t hash_value(const dynamic_bitset<B, A>& a);
#endif
public:
@@ -1623,6 +1627,17 @@ inline bool operator>=(const dynamic_bitset<Block, Allocator>& a,
}
//-----------------------------------------------------------------------------
+// hash operations
+
+template <typename Block, typename Allocator>
+inline std::size_t hash_value(const dynamic_bitset<Block, Allocator>& a)
+{
+ std::size_t res = hash_value(a.m_num_bits);
+ boost::hash_combine(res, a.m_bits);
+ return res;
+}
+
+//-----------------------------------------------------------------------------
// stream operations
#ifdef BOOST_OLD_IOSTREAMS
@@ -2106,8 +2121,26 @@ bool dynamic_bitset<Block, Allocator>::m_check_invariants() const
} // namespace boost
-
#undef BOOST_BITSET_CHAR
+// std::hash support
+#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) && !defined(BOOST_DYNAMIC_BITSET_NO_STD_HASH)
+#include <functional>
+namespace std
+{
+ template<typename Block, typename Allocator>
+ struct hash< boost::dynamic_bitset<Block, Allocator> >
+ {
+ typedef boost::dynamic_bitset<Block, Allocator> argument_type;
+ typedef std::size_t result_type;
+ result_type operator()(const argument_type& a) const BOOST_NOEXCEPT
+ {
+ boost::hash<argument_type> hasher;
+ return hasher(a);
+ }
+ };
+}
+#endif
+
#endif // include guard
diff --git a/boost/endian/arithmetic.hpp b/boost/endian/arithmetic.hpp
index 38e8bdcf31..5e77c9919e 100644
--- a/boost/endian/arithmetic.hpp
+++ b/boost/endian/arithmetic.hpp
@@ -2,6 +2,7 @@
// (C) Copyright Darin Adler 2000
// (C) Copyright Beman Dawes 2006, 2009, 2014
+// (C) Copyright Peter Dimov 2019
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
@@ -26,29 +27,20 @@
# pragma warning(disable:4365) // conversion ... signed/unsigned mismatch
#endif
-#ifdef BOOST_ENDIAN_LOG
-# include <iostream>
-#endif
-
-#if defined(__BORLANDC__) || defined( __CODEGEARC__)
-# pragma pack(push, 1)
-#endif
-
-#include <boost/config.hpp>
-#include <boost/config/workaround.hpp>
-#include <boost/predef/other/endian.h>
-#include <boost/endian/conversion.hpp>
#include <boost/endian/buffers.hpp>
-#define BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
-#include <boost/endian/detail/cover_operators.hpp>
-#undef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
-#include <boost/type_traits/is_signed.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/static_assert.hpp>
#include <boost/core/scoped_enum.hpp>
+#include <boost/predef/other/endian.h>
+#include <boost/static_assert.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
#include <iosfwd>
#include <climits>
+#if defined(__BORLANDC__) || defined( __CODEGEARC__)
+# pragma pack(push, 1)
+#endif
+
# if CHAR_BIT != 8
# error Platforms with CHAR_BIT != 8 are not supported
# endif
@@ -78,7 +70,7 @@ namespace endian
{
template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits,
- BOOST_SCOPED_ENUM(align) A = align::no>
+ BOOST_SCOPED_ENUM(align) Align = align::no>
class endian_arithmetic;
// big endian signed integer aligned types
@@ -190,216 +182,156 @@ namespace endian
typedef little_uint64_t native_uint64_t;
# endif
-# ifdef BOOST_ENDIAN_DEPRECATED_NAMES
+//---------------------------------- end synopsis ------------------------------------//
- typedef order endianness;
- typedef align alignment;
+template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits,
+ BOOST_SCOPED_ENUM(align) Align>
+class endian_arithmetic:
+ public endian_buffer<Order, T, n_bits, Align>
+{
+private:
-# ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES
- template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits,
- BOOST_SCOPED_ENUM(align) Align = align::no>
- using endian = endian_arithmetic<Order, T, n_bits, Align>;
-# endif
+ typedef endian_buffer<Order, T, n_bits, Align> inherited;
- // unaligned big endian signed integer types
- typedef endian_arithmetic< order::big, int_least8_t, 8 > big8_t;
- typedef endian_arithmetic< order::big, int_least16_t, 16 > big16_t;
- typedef endian_arithmetic< order::big, int_least32_t, 24 > big24_t;
- typedef endian_arithmetic< order::big, int_least32_t, 32 > big32_t;
- typedef endian_arithmetic< order::big, int_least64_t, 40 > big40_t;
- typedef endian_arithmetic< order::big, int_least64_t, 48 > big48_t;
- typedef endian_arithmetic< order::big, int_least64_t, 56 > big56_t;
- typedef endian_arithmetic< order::big, int_least64_t, 64 > big64_t;
-
- // unaligned big endian_arithmetic unsigned integer types
- typedef endian_arithmetic< order::big, uint_least8_t, 8 > ubig8_t;
- typedef endian_arithmetic< order::big, uint_least16_t, 16 > ubig16_t;
- typedef endian_arithmetic< order::big, uint_least32_t, 24 > ubig24_t;
- typedef endian_arithmetic< order::big, uint_least32_t, 32 > ubig32_t;
- typedef endian_arithmetic< order::big, uint_least64_t, 40 > ubig40_t;
- typedef endian_arithmetic< order::big, uint_least64_t, 48 > ubig48_t;
- typedef endian_arithmetic< order::big, uint_least64_t, 56 > ubig56_t;
- typedef endian_arithmetic< order::big, uint_least64_t, 64 > ubig64_t;
-
- // unaligned little endian_arithmetic signed integer types
- typedef endian_arithmetic< order::little, int_least8_t, 8 > little8_t;
- typedef endian_arithmetic< order::little, int_least16_t, 16 > little16_t;
- typedef endian_arithmetic< order::little, int_least32_t, 24 > little24_t;
- typedef endian_arithmetic< order::little, int_least32_t, 32 > little32_t;
- typedef endian_arithmetic< order::little, int_least64_t, 40 > little40_t;
- typedef endian_arithmetic< order::little, int_least64_t, 48 > little48_t;
- typedef endian_arithmetic< order::little, int_least64_t, 56 > little56_t;
- typedef endian_arithmetic< order::little, int_least64_t, 64 > little64_t;
-
- // unaligned little endian_arithmetic unsigned integer types
- typedef endian_arithmetic< order::little, uint_least8_t, 8 > ulittle8_t;
- typedef endian_arithmetic< order::little, uint_least16_t, 16 > ulittle16_t;
- typedef endian_arithmetic< order::little, uint_least32_t, 24 > ulittle24_t;
- typedef endian_arithmetic< order::little, uint_least32_t, 32 > ulittle32_t;
- typedef endian_arithmetic< order::little, uint_least64_t, 40 > ulittle40_t;
- typedef endian_arithmetic< order::little, uint_least64_t, 48 > ulittle48_t;
- typedef endian_arithmetic< order::little, uint_least64_t, 56 > ulittle56_t;
- typedef endian_arithmetic< order::little, uint_least64_t, 64 > ulittle64_t;
-
- // unaligned native endian_arithmetic signed integer types
- typedef endian_arithmetic< order::native, int_least8_t, 8 > native8_t;
- typedef endian_arithmetic< order::native, int_least16_t, 16 > native16_t;
- typedef endian_arithmetic< order::native, int_least32_t, 24 > native24_t;
- typedef endian_arithmetic< order::native, int_least32_t, 32 > native32_t;
- typedef endian_arithmetic< order::native, int_least64_t, 40 > native40_t;
- typedef endian_arithmetic< order::native, int_least64_t, 48 > native48_t;
- typedef endian_arithmetic< order::native, int_least64_t, 56 > native56_t;
- typedef endian_arithmetic< order::native, int_least64_t, 64 > native64_t;
-
- // unaligned native endian_arithmetic unsigned integer types
- typedef endian_arithmetic< order::native, uint_least8_t, 8 > unative8_t;
- typedef endian_arithmetic< order::native, uint_least16_t, 16 > unative16_t;
- typedef endian_arithmetic< order::native, uint_least32_t, 24 > unative24_t;
- typedef endian_arithmetic< order::native, uint_least32_t, 32 > unative32_t;
- typedef endian_arithmetic< order::native, uint_least64_t, 40 > unative40_t;
- typedef endian_arithmetic< order::native, uint_least64_t, 48 > unative48_t;
- typedef endian_arithmetic< order::native, uint_least64_t, 56 > unative56_t;
- typedef endian_arithmetic< order::native, uint_least64_t, 64 > unative64_t;
-
- // aligned native endian_arithmetic typedefs are not provided because
- // <cstdint> types are superior for this use case
-
- typedef endian_arithmetic< order::big, int16_t, 16, align::yes > aligned_big16_t;
- typedef endian_arithmetic< order::big, uint16_t, 16, align::yes > aligned_ubig16_t;
- typedef endian_arithmetic< order::little, int16_t, 16, align::yes > aligned_little16_t;
- typedef endian_arithmetic< order::little, uint16_t, 16, align::yes > aligned_ulittle16_t;
-
- typedef endian_arithmetic< order::big, int32_t, 32, align::yes > aligned_big32_t;
- typedef endian_arithmetic< order::big, uint32_t, 32, align::yes > aligned_ubig32_t;
- typedef endian_arithmetic< order::little, int32_t, 32, align::yes > aligned_little32_t;
- typedef endian_arithmetic< order::little, uint32_t, 32, align::yes > aligned_ulittle32_t;
-
- typedef endian_arithmetic< order::big, int64_t, 64, align::yes > aligned_big64_t;
- typedef endian_arithmetic< order::big, uint64_t, 64, align::yes > aligned_ubig64_t;
- typedef endian_arithmetic< order::little, int64_t, 64, align::yes > aligned_little64_t;
- typedef endian_arithmetic< order::little, uint64_t, 64, align::yes > aligned_ulittle64_t;
+public:
-# endif
+ typedef T value_type;
-//---------------------------------- end synopsis ------------------------------------//
+#ifndef BOOST_ENDIAN_NO_CTORS
-// endian class template specializations ---------------------------------------------//
+ endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
- // Specializations that represent unaligned bytes.
- // Taking an integer type as a parameter provides a nice way to pass both
- // the size and signness of the desired integer and get the appropriate
- // corresponding integer type for the interface.
+ BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic( T val ) BOOST_NOEXCEPT: inherited( val )
+ {
+ }
- // unaligned integer big endian specialization
- template <typename T, std::size_t n_bits>
- class endian_arithmetic< order::big, T, n_bits, align::no >
- : public endian_buffer< order::big, T, n_bits, align::no >,
- cover_operators<endian_arithmetic<order::big, T, n_bits>, T>
+#endif
+
+ endian_arithmetic& operator=( T val ) BOOST_NOEXCEPT
{
- BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
- public:
- typedef T value_type;
-# ifndef BOOST_ENDIAN_NO_CTORS
- endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
- BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "big, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
-# endif
- detail::store_big_endian<T, n_bits/8>(this->m_value, val);
- }
-# endif
- endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
- { detail::store_big_endian<T, n_bits/8>(this->m_value, val); return *this; }
- operator value_type() const BOOST_NOEXCEPT { return this->value(); }
- };
-
- // unaligned little endian specialization
- template <typename T, std::size_t n_bits>
- class endian_arithmetic< order::little, T, n_bits, align::no >
- : public endian_buffer< order::little, T, n_bits, align::no >,
- cover_operators< endian_arithmetic< order::little, T, n_bits >, T >
+ inherited::operator=( val );
+ return *this;
+ }
+
+ operator value_type() const BOOST_NOEXCEPT
{
- BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
- public:
- typedef T value_type;
-# ifndef BOOST_ENDIAN_NO_CTORS
- endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
- BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "little, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
-# endif
- detail::store_little_endian<T, n_bits/8>(this->m_value, val);
- }
-# endif
- endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
- { detail::store_little_endian<T, n_bits/8>(this->m_value, val); return *this; }
- operator value_type() const BOOST_NOEXCEPT { return this->value(); }
- };
-
- // align::yes specializations; only n_bits == 16/32/64 supported
-
- // aligned big endian specialization
- template <typename T, std::size_t n_bits>
- class endian_arithmetic<order::big, T, n_bits, align::yes>
- : public endian_buffer< order::big, T, n_bits, align::yes >,
- cover_operators<endian_arithmetic<order::big, T, n_bits, align::yes>, T>
+ return this->value();
+ }
+
+ // operators
+
+ T operator+() const BOOST_NOEXCEPT
{
- BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
- BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
- public:
- typedef T value_type;
-# ifndef BOOST_ENDIAN_NO_CTORS
- endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
- BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "big, aligned, " << n_bits << "-bits, construct(" << val << ")\n";
-# endif
- this->m_value = ::boost::endian::native_to_big(val);
- }
+ return this->value();
+ }
-# endif
- endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
- {
- this->m_value = ::boost::endian::native_to_big(val);
- return *this;
- }
- operator value_type() const BOOST_NOEXCEPT { return this->value(); }
- };
-
- // aligned little endian specialization
- template <typename T, std::size_t n_bits>
- class endian_arithmetic<order::little, T, n_bits, align::yes>
- : public endian_buffer< order::little, T, n_bits, align::yes >,
- cover_operators<endian_arithmetic<order::little, T, n_bits, align::yes>, T>
+ endian_arithmetic& operator+=( T y ) BOOST_NOEXCEPT
{
- BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
- BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
- public:
- typedef T value_type;
-# ifndef BOOST_ENDIAN_NO_CTORS
- endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
- BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "little, aligned, " << n_bits << "-bits, construct(" << val << ")\n";
-# endif
- this->m_value = ::boost::endian::native_to_little(val);
- }
-# endif
- endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
+ *this = static_cast<T>( this->value() + y );
+ return *this;
+ }
+
+ endian_arithmetic& operator-=( T y ) BOOST_NOEXCEPT
+ {
+ *this = static_cast<T>( this->value() - y );
+ return *this;
+ }
+
+ endian_arithmetic& operator*=( T y ) BOOST_NOEXCEPT
+ {
+ *this = static_cast<T>( this->value() * y );
+ return *this;
+ }
+
+ endian_arithmetic& operator/=( T y ) BOOST_NOEXCEPT
+ {
+ *this = static_cast<T>( this->value() / y );
+ return *this;
+ }
+
+ endian_arithmetic& operator%=( T y ) BOOST_NOEXCEPT
+ {
+ *this = static_cast<T>( this->value() % y );
+ return *this;
+ }
+
+ endian_arithmetic& operator&=( T y ) BOOST_NOEXCEPT
+ {
+ *this = static_cast<T>( this->value() & y );
+ return *this;
+ }
+
+ endian_arithmetic& operator|=( T y ) BOOST_NOEXCEPT
+ {
+ *this = static_cast<T>( this->value() | y );
+ return *this;
+ }
+
+ endian_arithmetic& operator^=( T y ) BOOST_NOEXCEPT
+ {
+ *this = static_cast<T>( this->value() ^ y );
+ return *this;
+ }
+
+ endian_arithmetic& operator<<=( T y ) BOOST_NOEXCEPT
+ {
+ *this = static_cast<T>( this->value() << y );
+ return *this;
+ }
+
+ endian_arithmetic& operator>>=( T y ) BOOST_NOEXCEPT
+ {
+ *this = static_cast<T>( this->value() >> y );
+ return *this;
+ }
+
+ endian_arithmetic& operator++() BOOST_NOEXCEPT
+ {
+ *this += 1;
+ return *this;
+ }
+
+ endian_arithmetic& operator--() BOOST_NOEXCEPT
+ {
+ *this -= 1;
+ return *this;
+ }
+
+ endian_arithmetic operator++(int) BOOST_NOEXCEPT
+ {
+ endian_arithmetic tmp( *this );
+ *this += 1;
+ return tmp;
+ }
+
+ endian_arithmetic operator--(int) BOOST_NOEXCEPT
+ {
+ endian_arithmetic tmp( *this );
+ *this -= 1;
+ return tmp;
+ }
+
+ template<class Ch, class Tr>
+ friend std::basic_ostream<Ch, Tr>&
+ operator<<( std::basic_ostream<Ch, Tr>& os, endian_arithmetic const& x )
+ {
+ return os << x.value();
+ }
+
+ template<class Ch, class Tr>
+ friend std::basic_istream<Ch, Tr>&
+ operator>>( std::basic_istream<Ch, Tr>& is, endian_arithmetic& x )
+ {
+ T i;
+
+ if( is >> i )
{
- this->m_value = ::boost::endian::native_to_little(val);
- return *this;
+ x = i;
}
- operator value_type() const BOOST_NOEXCEPT { return this->value(); }
- };
+
+ return is;
+ }
+};
} // namespace endian
} // namespace boost
diff --git a/boost/endian/buffers.hpp b/boost/endian/buffers.hpp
index 829d18b8e8..46f6eb7e33 100644
--- a/boost/endian/buffers.hpp
+++ b/boost/endian/buffers.hpp
@@ -2,6 +2,7 @@
// (C) Copyright Darin Adler 2000
// (C) Copyright Beman Dawes 2006, 2009, 2014
+// (C) Copyright Peter Dimov 2019
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
@@ -26,30 +27,22 @@
# pragma warning(disable: 4127) // conditional expression is constant
#endif
-#ifdef BOOST_ENDIAN_LOG
-# include <iostream>
-#endif
-
-#if defined(__BORLANDC__) || defined( __CODEGEARC__)
-# pragma pack(push, 1)
-#endif
-
-#include <boost/config.hpp>
-#include <boost/config/workaround.hpp>
+#include <boost/endian/detail/endian_store.hpp>
+#include <boost/endian/detail/endian_load.hpp>
+#include <boost/core/scoped_enum.hpp>
#include <boost/predef/other/endian.h>
-#include <boost/endian/conversion.hpp>
-#include <boost/type_traits/is_signed.hpp>
-#include <boost/type_traits/make_unsigned.hpp>
-#include <boost/type_traits/conditional.hpp>
-#include <boost/type_traits/is_integral.hpp>
-#include <boost/type_traits/type_identity.hpp>
-#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
-#include <boost/core/scoped_enum.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
#include <iosfwd>
#include <climits>
#include <cstring>
+#if defined(__BORLANDC__) || defined( __CODEGEARC__)
+# pragma pack(push, 1)
+#endif
+
# if CHAR_BIT != 8
# error Platforms with CHAR_BIT != 8 are not supported
# endif
@@ -217,323 +210,153 @@ namespace endian
//---------------------------------- end synopsis ------------------------------------//
- namespace detail
- {
+// endian_buffer class template specializations --------------------------------------//
+
+// Specializations that represent unaligned bytes.
+// Taking an integer type as a parameter provides a nice way to pass both
+// the size and signedness of the desired integer and get the appropriate
+// corresponding integer type for the interface.
+
+// Q: Should endian_buffer supply "value_type operator value_type() const noexcept"?
+// A: No. The rationale for endian_buffers is to prevent high-cost hidden
+// conversions. If an implicit conversion operator is supplied, hidden conversions
+// can occur.
+
+// unaligned endian_buffer specialization
+
+template< BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits >
+class endian_buffer<Order, T, n_bits, align::no>
+{
+private:
+
+ BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
+
+ unsigned char value_[ n_bits / 8 ];
- // Unrolled loops for loading and storing streams of bytes.
+public:
- template <typename T, std::size_t n_bytes,
- bool sign=boost::is_signed<T>::value >
- struct unrolled_byte_loops
+ typedef T value_type;
+
+#ifndef BOOST_ENDIAN_NO_CTORS
+
+ endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
+
+ explicit endian_buffer( T val ) BOOST_NOEXCEPT
{
- typedef unrolled_byte_loops<T, n_bytes - 1, sign> next;
-
- // shifting a negative number is flagged by -fsanitize=undefined
- // so use the corresponding unsigned type for the shifts
-
- typedef typename boost::conditional<
- boost::is_integral<T>::value,
- boost::make_unsigned<T>, boost::type_identity<T> >::type::type U;
-
- static T load_big(const unsigned char* bytes) BOOST_NOEXCEPT
- { return static_cast<T>(*(bytes - 1) | (static_cast<U>(next::load_big(bytes - 1)) << 8)); }
- static T load_little(const unsigned char* bytes) BOOST_NOEXCEPT
- { return static_cast<T>(*bytes | (static_cast<U>(next::load_little(bytes + 1)) << 8)); }
-
- static void store_big(unsigned char* bytes, T value) BOOST_NOEXCEPT
- {
- *(bytes - 1) = static_cast<unsigned char>(value);
- next::store_big(bytes - 1, static_cast<T>(static_cast<U>(value) >> 8));
- }
- static void store_little(unsigned char* bytes, T value) BOOST_NOEXCEPT
- {
- *bytes = static_cast<unsigned char>(value);
- next::store_little(bytes + 1, static_cast<T>(static_cast<U>(value) >> 8));
- }
- };
+ boost::endian::endian_store<T, n_bits / 8, Order>( value_, val );
+ }
- template <typename T>
- struct unrolled_byte_loops<T, 1, false>
+#endif
+
+ endian_buffer& operator=( T val ) BOOST_NOEXCEPT
{
- static T load_big(const unsigned char* bytes) BOOST_NOEXCEPT
- { return *(bytes - 1); }
- static T load_little(const unsigned char* bytes) BOOST_NOEXCEPT
- { return *bytes; }
- static void store_big(unsigned char* bytes, T value) BOOST_NOEXCEPT
- { *(bytes - 1) = static_cast<unsigned char>(value); }
- static void store_little(unsigned char* bytes, T value) BOOST_NOEXCEPT
- { *bytes = static_cast<unsigned char>(value); }
+ boost::endian::endian_store<T, n_bits / 8, Order>( value_, val );
+ return *this;
+ }
- };
+ value_type value() const BOOST_NOEXCEPT
+ {
+ return boost::endian::endian_load<T, n_bits / 8, Order>( value_ );
+ }
+
+ char const * data() const BOOST_NOEXCEPT
+ {
+ return reinterpret_cast< char const* >( value_ );
+ }
+};
+
+// aligned specializations; only n_bits == 16/32/64 supported
+
+// aligned endian_buffer specialization
+
+template< BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits >
+class endian_buffer<Order, T, n_bits, align::yes>
+{
+private:
- template <typename T>
- struct unrolled_byte_loops<T, 1, true>
+ BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
+ BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
+
+ union
{
- static T load_big(const unsigned char* bytes) BOOST_NOEXCEPT
- { return *reinterpret_cast<const signed char*>(bytes - 1); }
- static T load_little(const unsigned char* bytes) BOOST_NOEXCEPT
- { return *reinterpret_cast<const signed char*>(bytes); }
- static void store_big(unsigned char* bytes, T value) BOOST_NOEXCEPT
- { *(bytes - 1) = static_cast<unsigned char>(value); }
- static void store_little(unsigned char* bytes, T value) BOOST_NOEXCEPT
- { *bytes = static_cast<unsigned char>(value); }
+ unsigned char value_[ n_bits / 8 ];
+ T align_;
};
- template <typename T, std::size_t n_bytes>
- inline
- T load_big_endian(const void* bytes) BOOST_NOEXCEPT
+public:
+
+ typedef T value_type;
+
+#ifndef BOOST_ENDIAN_NO_CTORS
+
+ endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
+
+ explicit endian_buffer( T val ) BOOST_NOEXCEPT
{
-# if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
- // All major x86 compilers elide this test and optimize out memcpy
- // (the x86 architecture allows unaligned loads, but -fsanitize=undefined does not)
- if (sizeof(T) == n_bytes)
- {
- T t;
- std::memcpy( &t, bytes, sizeof(T) );
- return boost::endian::big_to_native(t);
- }
-# endif
- return unrolled_byte_loops<T, n_bytes>::load_big
- (static_cast<const unsigned char*>(bytes) + n_bytes);
+ boost::endian::endian_store<T, n_bits / 8, Order>( value_, val );
}
- template <typename T, std::size_t n_bytes>
- inline
- T load_little_endian(const void* bytes) BOOST_NOEXCEPT
+#endif
+
+ endian_buffer& operator=( T val ) BOOST_NOEXCEPT
{
-# if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
- // All major x86 compilers elide this test and optimize out memcpy
- // (the x86 architecture allows unaligned loads, but -fsanitize=undefined does not)
- if (sizeof(T) == n_bytes)
- {
- T t;
- std::memcpy( &t, bytes, sizeof(T) );
- return t; // or endian::little_to_native(t) if we ever extend the #ifdef to non-x86
- }
-# endif
- return unrolled_byte_loops<T, n_bytes>::load_little
- (static_cast<const unsigned char*>(bytes));
+ boost::endian::endian_store<T, n_bits / 8, Order>( value_, val );
+ return *this;
}
- template <typename T, std::size_t n_bytes>
- inline
- void store_big_endian(void* bytes, T value) BOOST_NOEXCEPT
+ value_type value() const BOOST_NOEXCEPT
{
-# if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
- // All major x86 compilers elide this test and optimize out memcpy
- // (the x86 architecture allows unaligned loads, but -fsanitize=undefined does not)
- if (sizeof(T) == n_bytes)
- {
- boost::endian::native_to_big_inplace(value);
- std::memcpy( bytes, &value, sizeof(T) );
- return;
- }
-# endif
- unrolled_byte_loops<T, n_bytes>::store_big
- (static_cast<unsigned char*>(bytes) + n_bytes, value);
+ return boost::endian::endian_load<T, n_bits / 8, Order>( value_ );
}
- template <typename T, std::size_t n_bytes>
- inline
- void store_little_endian(void* bytes, T value) BOOST_NOEXCEPT
+ char const * data() const BOOST_NOEXCEPT
{
-# if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
- // All major x86 compilers elide this test and optimize out memcpy
- // (the x86 architecture allows unaligned loads, but -fsanitize=undefined does not)
- if (sizeof(T) == n_bytes)
- {
- // if we ever extend the #ifdef to non-x86:
- // endian::native_to_little_inplace(value);
- std::memcpy( bytes, &value, sizeof(T) );
- return;
- }
-# endif
- unrolled_byte_loops<T, n_bytes>::store_little
- (static_cast<unsigned char*>(bytes), value);
+ return reinterpret_cast< char const* >( value_ );
}
+};
- } // namespace detail
+// aligned native endian_buffer specialization
-# ifdef BOOST_ENDIAN_LOG
- bool endian_log(true);
-# endif
+template< class T, std::size_t n_bits >
+class endian_buffer<order::native, T, n_bits, align::yes>
+{
+private:
-// endian_buffer class template specializations --------------------------------------//
+ BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
+ BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
- // Specializations that represent unaligned bytes.
- // Taking an integer type as a parameter provides a nice way to pass both
- // the size and signedness of the desired integer and get the appropriate
- // corresponding integer type for the interface.
+ T value_;
- // Q: Should endian_buffer supply "value_type operator value_type() const noexcept"?
- // A: No. The rationale for endian_buffers is to prevent high-cost hidden
- // conversions. If an implicit conversion operator is supplied, hidden conversions
- // can occur.
+public:
- // unaligned big endian_buffer specialization
- template <typename T, std::size_t n_bits>
- class endian_buffer< order::big, T, n_bits, align::no >
- {
- BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
- public:
- typedef T value_type;
-# ifndef BOOST_ENDIAN_NO_CTORS
- endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
- explicit endian_buffer(T val) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "big, unaligned, "
- << n_bits << "-bits, construct(" << val << ")\n";
-# endif
- detail::store_big_endian<T, n_bits/8>(m_value, val);
- }
-# endif
- endian_buffer & operator=(T val) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if (endian_log)
- std::cout << "big, unaligned, " << n_bits << "-bits, assign(" << val << ")\n";
-# endif
- detail::store_big_endian<T, n_bits/8>(m_value, val);
- return *this;
- }
- value_type value() const BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "big, unaligned, " << n_bits << "-bits, convert("
- << detail::load_big_endian<T, n_bits/8>(m_value) << ")\n";
-# endif
- return detail::load_big_endian<T, n_bits/8>(m_value);
- }
- const char* data() const BOOST_NOEXCEPT { return m_value; }
- protected:
- char m_value[n_bits/8];
- };
+ typedef T value_type;
- // unaligned little endian_buffer specialization
- template <typename T, std::size_t n_bits>
- class endian_buffer< order::little, T, n_bits, align::no >
+#ifndef BOOST_ENDIAN_NO_CTORS
+
+ endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
+
+ explicit endian_buffer( T val ) BOOST_NOEXCEPT: value_( val )
{
- BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
- public:
- typedef T value_type;
-# ifndef BOOST_ENDIAN_NO_CTORS
- endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
- explicit endian_buffer(T val) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "little, unaligned, " << n_bits << "-bits, construct("
- << val << ")\n";
-# endif
- detail::store_little_endian<T, n_bits/8>(m_value, val);
- }
-# endif
- endian_buffer & operator=(T val) BOOST_NOEXCEPT
- { detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
- value_type value() const BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "little, unaligned, " << n_bits << "-bits, convert("
- << detail::load_little_endian<T, n_bits/8>(m_value) << ")\n";
-# endif
- return detail::load_little_endian<T, n_bits/8>(m_value);
- }
- const char* data() const BOOST_NOEXCEPT { return m_value; }
- protected:
- char m_value[n_bits/8];
- };
+ }
- // align::yes specializations; only n_bits == 16/32/64 supported
+#endif
- // aligned big endian_buffer specialization
- template <typename T, std::size_t n_bits>
- class endian_buffer<order::big, T, n_bits, align::yes>
+ endian_buffer& operator=( T val ) BOOST_NOEXCEPT
{
- BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
- BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
- public:
- typedef T value_type;
-# ifndef BOOST_ENDIAN_NO_CTORS
- endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
- explicit endian_buffer(T val) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "big, aligned, " << n_bits
- << "-bits, construct(" << val << ")\n";
-# endif
- m_value = ::boost::endian::native_to_big(val);
- }
-
-# endif
- endian_buffer& operator=(T val) BOOST_NOEXCEPT
- {
- m_value = ::boost::endian::native_to_big(val);
- return *this;
- }
- //operator value_type() const BOOST_NOEXCEPT
- //{
- // return ::boost::endian::big_to_native(m_value);
- //}
- value_type value() const BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "big, aligned, " << n_bits << "-bits, convert("
- << ::boost::endian::big_to_native(m_value) << ")\n";
-# endif
- return ::boost::endian::big_to_native(m_value);
- }
- const char* data() const BOOST_NOEXCEPT
- {return reinterpret_cast<const char*>(&m_value);}
- protected:
- T m_value;
- };
+ value_ = val;
+ return *this;
+ }
- // aligned little endian_buffer specialization
- template <typename T, std::size_t n_bits>
- class endian_buffer<order::little, T, n_bits, align::yes>
+ value_type value() const BOOST_NOEXCEPT
{
- BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
- BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
- public:
- typedef T value_type;
-# ifndef BOOST_ENDIAN_NO_CTORS
- endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
- explicit endian_buffer(T val) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "little, aligned, " << n_bits
- << "-bits, construct(" << val << ")\n";
-# endif
- m_value = ::boost::endian::native_to_little(val);
- }
-
-# endif
- endian_buffer& operator=(T val) BOOST_NOEXCEPT
- {
- m_value = ::boost::endian::native_to_little(val);
- return *this;
- }
- value_type value() const BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_LOG
- if ( endian_log )
- std::cout << "little, aligned, " << n_bits << "-bits, convert("
- << ::boost::endian::little_to_native(m_value) << ")\n";
-# endif
- return ::boost::endian::little_to_native(m_value);
- }
- const char* data() const BOOST_NOEXCEPT
- {return reinterpret_cast<const char*>(&m_value);}
- protected:
- T m_value;
- };
+ return value_;
+ }
+
+ char const * data() const BOOST_NOEXCEPT
+ {
+ return reinterpret_cast< char const* >( &value_ );
+ }
+};
} // namespace endian
} // namespace boost
diff --git a/boost/endian/conversion.hpp b/boost/endian/conversion.hpp
index 9da4225e21..32ef5c58bc 100644
--- a/boost/endian/conversion.hpp
+++ b/boost/endian/conversion.hpp
@@ -8,14 +8,18 @@
#ifndef BOOST_ENDIAN_CONVERSION_HPP
#define BOOST_ENDIAN_CONVERSION_HPP
-#include <boost/config.hpp>
+#include <boost/endian/detail/endian_reverse.hpp>
+#include <boost/endian/detail/endian_load.hpp>
+#include <boost/endian/detail/endian_store.hpp>
+#include <boost/endian/detail/order.hpp>
+#include <boost/type_traits/is_class.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/integral_constant.hpp>
#include <boost/predef/other/endian.h>
-#include <boost/cstdint.hpp>
-#include <boost/endian/detail/intrinsic.hpp>
-#include <boost/core/scoped_enum.hpp>
#include <boost/static_assert.hpp>
-#include <algorithm>
-#include <cstring> // for memcpy
+#include <boost/cstdint.hpp>
+#include <boost/config.hpp>
//------------------------------------- synopsis ---------------------------------------//
@@ -23,15 +27,6 @@ namespace boost
{
namespace endian
{
- BOOST_SCOPED_ENUM_START(order)
- {
- big, little,
-# if BOOST_ENDIAN_BIG_BYTE
- native = big
-# else
- native = little
-# endif
- }; BOOST_SCOPED_ENUM_END
//--------------------------------------------------------------------------------------//
// //
@@ -49,19 +44,10 @@ namespace endian
// //
//--------------------------------------------------------------------------------------//
- // customization for exact-length arithmetic types. See doc/conversion.html/#FAQ.
- // Note: The omission of a overloads for the arithmetic type (typically long, or
- // long long) not assigned to one of the exact length typedefs is a deliberate
- // design decision. Such overloads would be non-portable and thus error prone.
-
- inline int8_t endian_reverse(int8_t x) BOOST_NOEXCEPT;
- inline int16_t endian_reverse(int16_t x) BOOST_NOEXCEPT;
- inline int32_t endian_reverse(int32_t x) BOOST_NOEXCEPT;
- inline int64_t endian_reverse(int64_t x) BOOST_NOEXCEPT;
- inline uint8_t endian_reverse(uint8_t x) BOOST_NOEXCEPT;
- inline uint16_t endian_reverse(uint16_t x) BOOST_NOEXCEPT;
- inline uint32_t endian_reverse(uint32_t x) BOOST_NOEXCEPT;
- inline uint64_t endian_reverse(uint64_t x) BOOST_NOEXCEPT;
+ // reverse byte order
+ // requires T to be a non-bool integral type
+ // in detail/endian_reverse.hpp
+ template<class T> inline T endian_reverse( T x ) BOOST_NOEXCEPT;
// reverse byte order unless native endianness is big
template <class EndianReversible >
@@ -123,6 +109,7 @@ namespace endian
//------------------------------------------------------------------------------------//
// reverse in place
+ // in detail/endian_reverse.hpp
template <class EndianReversible>
inline void endian_reverse_inplace(EndianReversible& x) BOOST_NOEXCEPT;
// Effects: x = endian_reverse(x)
@@ -156,335 +143,241 @@ namespace endian
//----------------------------------- end synopsis -------------------------------------//
- namespace detail
- {
- // generic reverse function template implementation approach using std::reverse
- // suggested by Mathias Gaunard. Primary motivation for inclusion is to have an
- // independent implementation to test against.
+namespace detail
+{
- template <class T>
- inline T std_endian_reverse(T x) BOOST_NOEXCEPT
- {
- T tmp(x);
- std::reverse(
- reinterpret_cast<unsigned char*>(&tmp),
- reinterpret_cast<unsigned char*>(&tmp) + sizeof(T));
- return tmp;
- }
+template<class T> struct is_endian_reversible: boost::integral_constant<bool,
+ boost::is_class<T>::value || ( boost::is_integral<T>::value && !boost::is_same<T, bool>::value )>
+{
+};
- // conditional unaligned reverse copy, patterned after std::reverse_copy
- template <class T>
- inline void big_reverse_copy(T from, char* to) BOOST_NOEXCEPT;
- template <class T>
- inline void big_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT;
- template <class T>
- inline void little_reverse_copy(T from, char* to) BOOST_NOEXCEPT;
- template <class T>
- inline void little_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT;
- } // namespace detail
+} // namespace detail
-//--------------------------------------------------------------------------------------//
-// //
-// return-by-value implementation //
-// //
-// -- portable approach suggested by tymofey, with avoidance of undefined behavior //
-// as suggested by Giovanni Piero Deretta, with a further refinement suggested //
-// by Pyry Jahkola. //
-// -- intrinsic approach suggested by reviewers, and by David Stone, who provided //
-// his Boost licensed macro implementation (detail/intrinsic.hpp) //
-// //
-//--------------------------------------------------------------------------------------//
+template <class EndianReversible>
+inline EndianReversible big_to_native( EndianReversible x ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible<EndianReversible>::value );
+
+#if BOOST_ENDIAN_BIG_BYTE
- inline int8_t endian_reverse(int8_t x) BOOST_NOEXCEPT
- {
return x;
- }
- inline int16_t endian_reverse(int16_t x) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
- return (static_cast<uint16_t>(x) << 8)
- | (static_cast<uint16_t>(x) >> 8);
-# else
- return static_cast<int16_t>(
- BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(static_cast<uint16_t>(x)));
-# endif
- }
+#else
- inline int32_t endian_reverse(int32_t x) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
- uint32_t step16;
- step16 = static_cast<uint32_t>(x) << 16 | static_cast<uint32_t>(x) >> 16;
- return
- ((static_cast<uint32_t>(step16) << 8) & 0xff00ff00)
- | ((static_cast<uint32_t>(step16) >> 8) & 0x00ff00ff);
-# else
- return static_cast<int32_t>(
- BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(static_cast<uint32_t>(x)));
-# endif
- }
+ return endian_reverse(x);
- inline int64_t endian_reverse(int64_t x) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
- uint64_t step32, step16;
- step32 = static_cast<uint64_t>(x) << 32 | static_cast<uint64_t>(x) >> 32;
- step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16
- | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
- return static_cast<int64_t>((step16 & 0x00FF00FF00FF00FFULL) << 8
- | (step16 & 0xFF00FF00FF00FF00ULL) >> 8);
-# else
- return static_cast<int64_t>(
- BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(static_cast<uint64_t>(x)));
-# endif
+#endif
}
- inline uint8_t endian_reverse(uint8_t x) BOOST_NOEXCEPT
- {
- return x;
- }
+template <class EndianReversible>
+inline EndianReversible native_to_big( EndianReversible x ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible<EndianReversible>::value );
- inline uint16_t endian_reverse(uint16_t x) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
- return (x << 8)
- | (x >> 8);
-# else
- return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x);
-# endif
- }
+#if BOOST_ENDIAN_BIG_BYTE
- inline uint32_t endian_reverse(uint32_t x) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
- uint32_t step16;
- step16 = x << 16 | x >> 16;
- return
- ((step16 << 8) & 0xff00ff00)
- | ((step16 >> 8) & 0x00ff00ff);
-# else
- return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x);
-# endif
- }
+ return x;
- inline uint64_t endian_reverse(uint64_t x) BOOST_NOEXCEPT
- {
-# ifdef BOOST_ENDIAN_NO_INTRINSICS
- uint64_t step32, step16;
- step32 = x << 32 | x >> 32;
- step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16
- | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
- return (step16 & 0x00FF00FF00FF00FFULL) << 8
- | (step16 & 0xFF00FF00FF00FF00ULL) >> 8;
-# else
- return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x);
-# endif
- }
+#else
- template <class EndianReversible >
- inline EndianReversible big_to_native(EndianReversible x) BOOST_NOEXCEPT
- {
-# if BOOST_ENDIAN_BIG_BYTE
- return x;
-# else
return endian_reverse(x);
-# endif
- }
- template <class EndianReversible >
- inline EndianReversible native_to_big(EndianReversible x) BOOST_NOEXCEPT
- {
-# if BOOST_ENDIAN_BIG_BYTE
+#endif
+}
+
+template <class EndianReversible>
+inline EndianReversible little_to_native( EndianReversible x ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible<EndianReversible>::value );
+
+#if BOOST_ENDIAN_LITTLE_BYTE
+
return x;
-# else
+
+#else
+
return endian_reverse(x);
-# endif
- }
- template <class EndianReversible >
- inline EndianReversible little_to_native(EndianReversible x) BOOST_NOEXCEPT
- {
-# if BOOST_ENDIAN_LITTLE_BYTE
+#endif
+}
+
+template <class EndianReversible>
+inline EndianReversible native_to_little( EndianReversible x ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible<EndianReversible>::value );
+
+#if BOOST_ENDIAN_LITTLE_BYTE
+
return x;
-# else
+
+#else
+
return endian_reverse(x);
-# endif
- }
- template <class EndianReversible >
- inline EndianReversible native_to_little(EndianReversible x) BOOST_NOEXCEPT
- {
-# if BOOST_ENDIAN_LITTLE_BYTE
+#endif
+}
+
+namespace detail
+{
+
+template<class EndianReversible>
+inline EndianReversible conditional_reverse_impl( EndianReversible x, boost::true_type ) BOOST_NOEXCEPT
+{
return x;
-# else
- return endian_reverse(x);
-# endif
- }
+}
- namespace detail
- {
- // Primary template and specializations to support endian_reverse().
- // See rationale in endian_reverse() below.
- template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
- class EndianReversible>
- class value_converter ; // primary template
- template <class T> class value_converter <order::big, order::big, T>
- {public: T operator()(T x) BOOST_NOEXCEPT {return x;}};
- template <class T> class value_converter <order::little, order::little, T>
- {public: T operator()(T x) BOOST_NOEXCEPT {return x;}};
- template <class T> class value_converter <order::big, order::little, T>
- {public: T operator()(T x) BOOST_NOEXCEPT {return endian_reverse(x);}};
- template <class T> class value_converter <order::little, order::big, T>
- {public: T operator()(T x) BOOST_NOEXCEPT {return endian_reverse(x);}};
- }
+template<class EndianReversible>
+inline EndianReversible conditional_reverse_impl( EndianReversible x, boost::false_type ) BOOST_NOEXCEPT
+{
+ return endian_reverse( x );
+}
- // generic conditional reverse
- template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
- class EndianReversible>
- inline EndianReversible conditional_reverse(EndianReversible from) BOOST_NOEXCEPT {
- // work around lack of function template partial specialization by instantiating
- // a function object of a class that is partially specialized on the two order
- // template parameters, and then calling its operator().
- detail::value_converter <From, To, EndianReversible> tmp;
- return tmp(from);
- }
+} // namespace detail
- // runtime conditional reverse
- template <class EndianReversible >
- inline EndianReversible conditional_reverse(EndianReversible from,
- BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order) BOOST_NOEXCEPT
- {
- return from_order == to_order ? from : endian_reverse(from);
- }
+// generic conditional reverse
+template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To, class EndianReversible>
+inline EndianReversible conditional_reverse( EndianReversible x ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible<EndianReversible>::value );
+ return detail::conditional_reverse_impl( x, boost::integral_constant<bool, From == To>() );
+}
+
+// runtime conditional reverse
+template <class EndianReversible>
+inline EndianReversible conditional_reverse( EndianReversible x,
+ BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible<EndianReversible>::value );
+ return from_order == to_order? x: endian_reverse( x );
+}
//--------------------------------------------------------------------------------------//
// reverse-in-place implementation //
//--------------------------------------------------------------------------------------//
- // reverse in place
- template <class EndianReversible>
- inline void endian_reverse_inplace(EndianReversible& x) BOOST_NOEXCEPT
- {
- x = endian_reverse(x);
- }
+namespace detail
+{
- template <class EndianReversibleInplace>
-# if BOOST_ENDIAN_BIG_BYTE
- inline void big_to_native_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
-# else
- inline void big_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
- { endian_reverse_inplace(x); }
-# endif
- template <class EndianReversibleInplace>
-# if BOOST_ENDIAN_BIG_BYTE
- inline void native_to_big_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
-# else
- inline void native_to_big_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
- {
- endian_reverse_inplace(x);
- }
-# endif
+template<class T> struct is_endian_reversible_inplace: boost::integral_constant<bool,
+ boost::is_class<T>::value || ( boost::is_integral<T>::value && !boost::is_same<T, bool>::value )>
+{
+};
- template <class EndianReversibleInplace>
-# if BOOST_ENDIAN_LITTLE_BYTE
- inline void little_to_native_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
-# else
- inline void little_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
- { endian_reverse_inplace(x); }
-# endif
- template <class EndianReversibleInplace>
-# if BOOST_ENDIAN_LITTLE_BYTE
- inline void native_to_little_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
-# else
- inline void native_to_little_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
- {
- endian_reverse_inplace(x);
- }
-# endif
-
- namespace detail
- {
- // Primary template and specializations support generic
- // endian_reverse_inplace().
- // See rationale in endian_reverse_inplace() below.
- template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
- class EndianReversibleInplace>
- class converter; // primary template
- template <class T> class converter<order::big, order::big, T>
- {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}};
- template <class T> class converter<order::little, order::little, T>
- {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}};
- template <class T> class converter<order::big, order::little, T>
- {public: void operator()(T& x) BOOST_NOEXCEPT { endian_reverse_inplace(x); }};
- template <class T> class converter<order::little, order::big, T>
- {public: void operator()(T& x) BOOST_NOEXCEPT { endian_reverse_inplace(x); }};
- } // namespace detail
+} // namespace detail
- // generic conditional reverse in place
- template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
- class EndianReversibleInplace>
- inline void conditional_reverse_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
- {
- // work around lack of function template partial specialization by instantiating
- // a function object of a class that is partially specialized on the two order
- // template parameters, and then calling its operator().
- detail::converter<From, To, EndianReversibleInplace> tmp;
- tmp(x); // call operator ()
- }
+#if BOOST_ENDIAN_BIG_BYTE
- // runtime reverse in place
- template <class EndianReversibleInplace>
- inline void conditional_reverse_inplace(EndianReversibleInplace& x,
- BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order)
- BOOST_NOEXCEPT
- {
- if (from_order != to_order)
- endian_reverse_inplace(x);
- }
+template <class EndianReversibleInplace>
+inline void big_to_native_inplace( EndianReversibleInplace& ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
+}
+#else
- namespace detail
- {
- template <class T>
- inline void big_reverse_copy(T from, char* to) BOOST_NOEXCEPT
- {
-# if BOOST_ENDIAN_BIG_BYTE
- std::memcpy(to, reinterpret_cast<const char*>(&from), sizeof(T));
-# else
- std::reverse_copy(reinterpret_cast<const char*>(&from),
- reinterpret_cast<const char*>(&from) + sizeof(T), to);
-# endif
- }
- template <class T>
- inline void big_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT
- {
-# if BOOST_ENDIAN_BIG_BYTE
- std::memcpy(reinterpret_cast<char*>(&to), from, sizeof(T));
-# else
- std::reverse_copy(from, from + sizeof(T), reinterpret_cast<char*>(&to));
-# endif
- }
- template <class T>
- inline void little_reverse_copy(T from, char* to) BOOST_NOEXCEPT
- {
-# if BOOST_ENDIAN_LITTLE_BYTE
- std::memcpy(to, reinterpret_cast<const char*>(&from), sizeof(T));
-# else
- std::reverse_copy(reinterpret_cast<const char*>(&from),
- reinterpret_cast<const char*>(&from) + sizeof(T), to);
-# endif
- }
- template <class T>
- inline void little_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT
+template <class EndianReversibleInplace>
+inline void big_to_native_inplace( EndianReversibleInplace& x ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
+ endian_reverse_inplace( x );
+}
+
+#endif
+
+#if BOOST_ENDIAN_BIG_BYTE
+
+template <class EndianReversibleInplace>
+inline void native_to_big_inplace( EndianReversibleInplace& ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
+}
+
+#else
+
+template <class EndianReversibleInplace>
+inline void native_to_big_inplace( EndianReversibleInplace& x ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
+ endian_reverse_inplace( x );
+}
+
+#endif
+
+#if BOOST_ENDIAN_LITTLE_BYTE
+
+template <class EndianReversibleInplace>
+inline void little_to_native_inplace( EndianReversibleInplace& ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
+}
+
+#else
+
+template <class EndianReversibleInplace>
+inline void little_to_native_inplace( EndianReversibleInplace& x ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
+ endian_reverse_inplace( x );
+}
+
+#endif
+
+#if BOOST_ENDIAN_LITTLE_BYTE
+
+template <class EndianReversibleInplace>
+inline void native_to_little_inplace( EndianReversibleInplace& ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
+}
+
+#else
+
+template <class EndianReversibleInplace>
+inline void native_to_little_inplace( EndianReversibleInplace& x ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
+ endian_reverse_inplace( x );
+}
+
+#endif
+
+namespace detail
+{
+
+template<class EndianReversibleInplace>
+inline void conditional_reverse_inplace_impl( EndianReversibleInplace&, boost::true_type ) BOOST_NOEXCEPT
+{
+}
+
+template<class EndianReversibleInplace>
+inline void conditional_reverse_inplace_impl( EndianReversibleInplace& x, boost::false_type ) BOOST_NOEXCEPT
+{
+ endian_reverse_inplace( x );
+}
+
+} // namespace detail
+
+// generic conditional reverse in place
+template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To, class EndianReversibleInplace>
+inline void conditional_reverse_inplace( EndianReversibleInplace& x ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
+ detail::conditional_reverse_inplace_impl( x, boost::integral_constant<bool, From == To>() );
+}
+
+// runtime reverse in place
+template <class EndianReversibleInplace>
+inline void conditional_reverse_inplace( EndianReversibleInplace& x,
+ BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( detail::is_endian_reversible_inplace<EndianReversibleInplace>::value );
+
+ if( from_order != to_order )
{
-# if BOOST_ENDIAN_LITTLE_BYTE
- std::memcpy(reinterpret_cast<char*>(&to), from, sizeof(T));
-# else
- std::reverse_copy(from, from + sizeof(T), reinterpret_cast<char*>(&to));
-# endif
+ endian_reverse_inplace( x );
}
- } // namespace detail
+}
+
} // namespace endian
} // namespace boost
diff --git a/boost/endian/detail/cover_operators.hpp b/boost/endian/detail/cover_operators.hpp
deleted file mode 100644
index a16545e498..0000000000
--- a/boost/endian/detail/cover_operators.hpp
+++ /dev/null
@@ -1,142 +0,0 @@
-// boost/endian/detail/cover_operators.hpp ----------------------------------//
-
-// Copyright Darin Adler 2000
-// Copyright Beman Dawes 2008
-
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_ENDIAN_COVER_OPERATORS_HPP
-#define BOOST_ENDIAN_COVER_OPERATORS_HPP
-
-#if defined(_MSC_VER)
-# pragma warning(push)
-# pragma warning(disable:4365) // conversion ... signed/unsigned mismatch
-#endif
-
-# ifndef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
-# include <boost/operators.hpp>
-# endif
-
-#include <boost/config.hpp>
-#include <iosfwd>
-
-namespace boost
-{
- namespace endian
- {
-
-//--------------------------------------------------------------------------------------//
-
-// A class that adds arithmetic operators to an arithmetic cover class
-//
-// Uses the curiously recurring template pattern (CRTP).
-//
-// If the class being covered has a non-explicit conversion to an integer type
-// then a smaller number of cover operations are needed. Define the macro
-// BOOST_ENDIAN_MINIMAL_COVER_OPERATORS to indicate this.
-//
-// Define BOOST_NO_IO_COVER_OPERATORS if I/O cover operations are not desired.
-
-//--------------------------------------------------------------------------------------//
-
- template <class D, // D is the CRTP derived type, i.e. the cover class
- class ArithmeticT>
- class cover_operators
-# ifndef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
- : boost::operators<D>
-# endif
- {
- // The other operations take advantage of the type conversion that's
- // built into unary +.
-
- // Unary operations.
- friend ArithmeticT operator+(const D& x) BOOST_NOEXCEPT { return x; }
-# ifndef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
- friend ArithmeticT operator-(const D& x) BOOST_NOEXCEPT { return -+x; }
- friend ArithmeticT operator~(const D& x) BOOST_NOEXCEPT { return ~+x; }
- friend ArithmeticT operator!(const D& x) BOOST_NOEXCEPT { return !+x; }
-
- // The basic ordering operations.
- friend bool operator==(const D& x, ArithmeticT y) BOOST_NOEXCEPT { return +x == y; }
- friend bool operator<(const D& x, ArithmeticT y) BOOST_NOEXCEPT { return +x < y; }
-# endif
-
- // The basic arithmetic operations.
- friend D& operator+=(D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return x = static_cast<ArithmeticT>(+x + y); }
- friend D& operator-=(D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return x = static_cast<ArithmeticT>(+x - y); }
- friend D& operator*=(D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return x = static_cast<ArithmeticT>(+x * y); }
- friend D& operator/=(D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return x = static_cast<ArithmeticT>(+x / y); }
- friend D& operator%=(D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return x = static_cast<ArithmeticT>(+x % y); }
- friend D& operator&=(D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return x = static_cast<ArithmeticT>(+x & y); }
- friend D& operator|=(D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return x = static_cast<ArithmeticT>(+x | y); }
- friend D& operator^=(D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return x = static_cast<ArithmeticT>(+x ^ y); }
- friend D& operator<<=(D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return x = static_cast<ArithmeticT>(+x << y); }
- friend D& operator>>=(D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return x = static_cast<ArithmeticT>(+x >> y); }
-
- // A few binary arithmetic operations not covered by operators base class.
- friend ArithmeticT operator<<(const D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return static_cast<ArithmeticT>(+x << y); }
- friend ArithmeticT operator>>(const D& x, ArithmeticT y) BOOST_NOEXCEPT
- { return static_cast<ArithmeticT>(+x >> y); }
-
- // Auto-increment and auto-decrement can be defined in terms of the
- // arithmetic operations.
- friend D& operator++(D& x) BOOST_NOEXCEPT { return x += 1; }
- friend D& operator--(D& x) BOOST_NOEXCEPT { return x -= 1; }
-
-# ifdef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
- friend D operator++(D& x, int) BOOST_NOEXCEPT
- {
- D tmp(x);
- x += 1;
- return tmp;
- }
- friend D operator--(D& x, int) BOOST_NOEXCEPT
- {
- D tmp(x);
- x -= 1;
- return tmp;
- }
-# endif
-
-# ifndef BOOST_NO_IO_COVER_OPERATORS
-
- // Stream inserter
- template <class charT, class traits>
- friend std::basic_ostream<charT, traits>&
- operator<<(std::basic_ostream<charT, traits>& os, const D& x)
- {
- return os << +x;
- }
-
- // Stream extractor
- template <class charT, class traits>
- friend std::basic_istream<charT, traits>&
- operator>>(std::basic_istream<charT, traits>& is, D& x)
- {
- ArithmeticT i;
- if (is >> i)
- x = i;
- return is;
- }
-# endif
- };
- } // namespace endian
-} // namespace boost
-
-#if defined(_MSC_VER)
-# pragma warning(pop)
-#endif
-
-#endif // BOOST_ENDIAN_COVER_OPERATORS_HPP
diff --git a/boost/endian/detail/endian_load.hpp b/boost/endian/detail/endian_load.hpp
new file mode 100644
index 0000000000..8dd9a20b31
--- /dev/null
+++ b/boost/endian/detail/endian_load.hpp
@@ -0,0 +1,589 @@
+#ifndef BOOST_ENDIAN_DETAIL_ENDIAN_LOAD_HPP_INCLUDED
+#define BOOST_ENDIAN_DETAIL_ENDIAN_LOAD_HPP_INCLUDED
+
+// Copyright 2019 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/endian/detail/endian_reverse.hpp>
+#include <boost/endian/detail/order.hpp>
+#include <boost/endian/detail/integral_by_size.hpp>
+#include <boost/endian/detail/is_trivially_copyable.hpp>
+#include <boost/type_traits/is_signed.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/static_assert.hpp>
+#include <cstddef>
+#include <cstring>
+
+namespace boost
+{
+namespace endian
+{
+
+namespace detail
+{
+
+template<class T, std::size_t N1, BOOST_SCOPED_ENUM(order) O1, std::size_t N2, BOOST_SCOPED_ENUM(order) O2> struct endian_load_impl
+{
+};
+
+} // namespace detail
+
+// Requires:
+//
+// sizeof(T) must be 1, 2, 4, or 8
+// 1 <= N <= sizeof(T)
+// T is TriviallyCopyable
+// if N < sizeof(T), T is integral or enum
+
+template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) Order>
+inline T endian_load( unsigned char const * p ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8 );
+ BOOST_STATIC_ASSERT( N >= 1 && N <= sizeof(T) );
+
+ return detail::endian_load_impl<T, sizeof(T), order::native, N, Order>()( p );
+}
+
+namespace detail
+{
+
+// same endianness, same size
+
+template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O> struct endian_load_impl<T, N, O, N, O>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
+
+ T t;
+ std::memcpy( &t, p, N );
+ return t;
+ }
+};
+
+// same size, reverse endianness
+
+template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O1, BOOST_SCOPED_ENUM(order) O2> struct endian_load_impl<T, N, O1, N, O2>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
+
+ typename integral_by_size<N>::type tmp;
+ std::memcpy( &tmp, p, N );
+
+ endian_reverse_inplace( tmp );
+
+ T t;
+ std::memcpy( &t, &tmp, N );
+ return t;
+ }
+};
+
+// expanding load 1 -> 2
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 2, Order, 1, order::little>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 2 ];
+
+ tmp[0] = p[0];
+ tmp[1] = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ return boost::endian::endian_load<T, 2, order::little>( tmp );
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 2, Order, 1, order::big>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 2 ];
+
+ tmp[0] = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+ tmp[1] = p[0];
+
+ return boost::endian::endian_load<T, 2, order::big>( tmp );
+ }
+};
+
+// expanding load 1 -> 4
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 4, Order, 1, order::little>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = p[0];
+ tmp[1] = fill;
+ tmp[2] = fill;
+ tmp[3] = fill;
+
+ return boost::endian::endian_load<T, 4, order::little>( tmp );
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 4, Order, 1, order::big>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = fill;
+ tmp[1] = fill;
+ tmp[2] = fill;
+ tmp[3] = p[0];
+
+ return boost::endian::endian_load<T, 4, order::big>( tmp );
+ }
+};
+
+// expanding load 2 -> 4
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 4, Order, 2, order::little>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[1] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = p[0];
+ tmp[1] = p[1];
+ tmp[2] = fill;
+ tmp[3] = fill;
+
+ return boost::endian::endian_load<T, 4, order::little>( tmp );
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 4, Order, 2, order::big>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = fill;
+ tmp[1] = fill;
+ tmp[2] = p[0];
+ tmp[3] = p[1];
+
+ return boost::endian::endian_load<T, 4, order::big>( tmp );
+ }
+};
+
+// expanding load 3 -> 4
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 4, Order, 3, order::little>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+
+ tmp[0] = p[0];
+ tmp[1] = p[1];
+ tmp[2] = p[2];
+ tmp[3] = boost::is_signed<T>::value && ( p[2] & 0x80 )? 0xFF: 0x00;
+
+ return boost::endian::endian_load<T, 4, order::little>( tmp );
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 4, Order, 3, order::big>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+
+ tmp[0] = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+ tmp[1] = p[0];
+ tmp[2] = p[1];
+ tmp[3] = p[2];
+
+ return boost::endian::endian_load<T, 4, order::big>( tmp );
+ }
+};
+
+// expanding load 1 -> 8
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 1, order::little>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = p[0];
+
+ tmp[1] = fill;
+ tmp[2] = fill;
+ tmp[3] = fill;
+ tmp[4] = fill;
+ tmp[5] = fill;
+ tmp[6] = fill;
+ tmp[7] = fill;
+
+ return boost::endian::endian_load<T, 8, order::little>( tmp );
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 1, order::big>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = fill;
+ tmp[1] = fill;
+ tmp[2] = fill;
+ tmp[3] = fill;
+ tmp[4] = fill;
+ tmp[5] = fill;
+ tmp[6] = fill;
+
+ tmp[7] = p[0];
+
+ return boost::endian::endian_load<T, 8, order::big>( tmp );
+ }
+};
+
+// expanding load 2 -> 8
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 2, order::little>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[1] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = p[0];
+ tmp[1] = p[1];
+
+ tmp[2] = fill;
+ tmp[3] = fill;
+ tmp[4] = fill;
+ tmp[5] = fill;
+ tmp[6] = fill;
+ tmp[7] = fill;
+
+ return boost::endian::endian_load<T, 8, order::little>( tmp );
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 2, order::big>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = fill;
+ tmp[1] = fill;
+ tmp[2] = fill;
+ tmp[3] = fill;
+ tmp[4] = fill;
+ tmp[5] = fill;
+
+ tmp[6] = p[0];
+ tmp[7] = p[1];
+
+ return boost::endian::endian_load<T, 8, order::big>( tmp );
+ }
+};
+
+// expanding load 3 -> 8
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 3, order::little>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[2] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = p[0];
+ tmp[1] = p[1];
+ tmp[2] = p[2];
+
+ tmp[3] = fill;
+ tmp[4] = fill;
+ tmp[5] = fill;
+ tmp[6] = fill;
+ tmp[7] = fill;
+
+ return boost::endian::endian_load<T, 8, order::little>( tmp );
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 3, order::big>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = fill;
+ tmp[1] = fill;
+ tmp[2] = fill;
+ tmp[3] = fill;
+ tmp[4] = fill;
+
+ tmp[5] = p[0];
+ tmp[6] = p[1];
+ tmp[7] = p[2];
+
+ return boost::endian::endian_load<T, 8, order::big>( tmp );
+ }
+};
+
+// expanding load 4 -> 8
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 4, order::little>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[3] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = p[0];
+ tmp[1] = p[1];
+ tmp[2] = p[2];
+ tmp[3] = p[3];
+
+ tmp[4] = fill;
+ tmp[5] = fill;
+ tmp[6] = fill;
+ tmp[7] = fill;
+
+ return boost::endian::endian_load<T, 8, order::little>( tmp );
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 4, order::big>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = fill;
+ tmp[1] = fill;
+ tmp[2] = fill;
+ tmp[3] = fill;
+
+ tmp[4] = p[0];
+ tmp[5] = p[1];
+ tmp[6] = p[2];
+ tmp[7] = p[3];
+
+ return boost::endian::endian_load<T, 8, order::big>( tmp );
+ }
+};
+
+// expanding load 5 -> 8
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 5, order::little>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[4] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = p[0];
+ tmp[1] = p[1];
+ tmp[2] = p[2];
+ tmp[3] = p[3];
+ tmp[4] = p[4];
+
+ tmp[5] = fill;
+ tmp[6] = fill;
+ tmp[7] = fill;
+
+ return boost::endian::endian_load<T, 8, order::little>( tmp );
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 5, order::big>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = fill;
+ tmp[1] = fill;
+ tmp[2] = fill;
+
+ tmp[3] = p[0];
+ tmp[4] = p[1];
+ tmp[5] = p[2];
+ tmp[6] = p[3];
+ tmp[7] = p[4];
+
+ return boost::endian::endian_load<T, 8, order::big>( tmp );
+ }
+};
+
+// expanding load 6 -> 8
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 6, order::little>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[5] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = p[0];
+ tmp[1] = p[1];
+ tmp[2] = p[2];
+ tmp[3] = p[3];
+ tmp[4] = p[4];
+ tmp[5] = p[5];
+
+ tmp[6] = fill;
+ tmp[7] = fill;
+
+ return boost::endian::endian_load<T, 8, order::little>( tmp );
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 6, order::big>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = fill;
+ tmp[1] = fill;
+
+ tmp[2] = p[0];
+ tmp[3] = p[1];
+ tmp[4] = p[2];
+ tmp[5] = p[3];
+ tmp[6] = p[4];
+ tmp[7] = p[5];
+
+ return boost::endian::endian_load<T, 8, order::big>( tmp );
+ }
+};
+
+// expanding load 7 -> 8
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 7, order::little>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[6] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = p[0];
+ tmp[1] = p[1];
+ tmp[2] = p[2];
+ tmp[3] = p[3];
+ tmp[4] = p[4];
+ tmp[5] = p[5];
+ tmp[6] = p[6];
+
+ tmp[7] = fill;
+
+ return boost::endian::endian_load<T, 8, order::little>( tmp );
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_load_impl<T, 8, Order, 7, order::big>
+{
+ inline T operator()( unsigned char const * p ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+
+ unsigned char fill = boost::is_signed<T>::value && ( p[0] & 0x80 )? 0xFF: 0x00;
+
+ tmp[0] = fill;
+
+ tmp[1] = p[0];
+ tmp[2] = p[1];
+ tmp[3] = p[2];
+ tmp[4] = p[3];
+ tmp[5] = p[4];
+ tmp[6] = p[5];
+ tmp[7] = p[6];
+
+ return boost::endian::endian_load<T, 8, order::big>( tmp );
+ }
+};
+
+} // namespace detail
+
+} // namespace endian
+} // namespace boost
+
+#endif // BOOST_ENDIAN_DETAIL_ENDIAN_LOAD_HPP_INCLUDED
diff --git a/boost/endian/detail/endian_reverse.hpp b/boost/endian/detail/endian_reverse.hpp
new file mode 100644
index 0000000000..cb80c79da5
--- /dev/null
+++ b/boost/endian/detail/endian_reverse.hpp
@@ -0,0 +1,103 @@
+#ifndef BOOST_ENDIAN_DETAIL_ENDIAN_REVERSE_HPP_INCLUDED
+#define BOOST_ENDIAN_DETAIL_ENDIAN_REVERSE_HPP_INCLUDED
+
+// Copyright 2019 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/endian/detail/integral_by_size.hpp>
+#include <boost/endian/detail/intrinsic.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/config.hpp>
+#include <cstddef>
+#include <cstring>
+
+namespace boost
+{
+namespace endian
+{
+
+namespace detail
+{
+
+// -- portable approach suggested by tymofey, with avoidance of undefined behavior
+// as suggested by Giovanni Piero Deretta, with a further refinement suggested
+// by Pyry Jahkola.
+// -- intrinsic approach suggested by reviewers, and by David Stone, who provided
+// his Boost licensed macro implementation (detail/intrinsic.hpp)
+
+inline uint8_t endian_reverse_impl( uint8_t x ) BOOST_NOEXCEPT
+{
+ return x;
+}
+
+inline uint16_t endian_reverse_impl( uint16_t x ) BOOST_NOEXCEPT
+{
+#ifdef BOOST_ENDIAN_NO_INTRINSICS
+
+ return (x << 8) | (x >> 8);
+
+#else
+
+ return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x);
+
+#endif
+}
+
+inline uint32_t endian_reverse_impl(uint32_t x) BOOST_NOEXCEPT
+{
+#ifdef BOOST_ENDIAN_NO_INTRINSICS
+
+ uint32_t step16 = x << 16 | x >> 16;
+ return ((step16 << 8) & 0xff00ff00) | ((step16 >> 8) & 0x00ff00ff);
+
+#else
+
+ return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x);
+
+#endif
+}
+
+inline uint64_t endian_reverse_impl(uint64_t x) BOOST_NOEXCEPT
+{
+#ifdef BOOST_ENDIAN_NO_INTRINSICS
+
+ uint64_t step32 = x << 32 | x >> 32;
+ uint64_t step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
+ return (step16 & 0x00FF00FF00FF00FFULL) << 8 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8;
+
+#else
+
+ return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x);
+
+# endif
+}
+
+} // namespace detail
+
+// Requires:
+// T is non-bool integral
+
+template<class T> inline T endian_reverse( T x ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( is_integral<T>::value && !is_same<T, bool>::value );
+
+ typedef typename detail::integral_by_size< sizeof(T) >::type uintN_t;
+
+ return static_cast<T>( detail::endian_reverse_impl( static_cast<uintN_t>( x ) ) );
+}
+
+template <class EndianReversible>
+inline void endian_reverse_inplace(EndianReversible& x) BOOST_NOEXCEPT
+{
+ x = endian_reverse( x );
+}
+
+} // namespace endian
+} // namespace boost
+
+#endif // BOOST_ENDIAN_DETAIL_ENDIAN_REVERSE_HPP_INCLUDED
diff --git a/boost/endian/detail/endian_store.hpp b/boost/endian/detail/endian_store.hpp
new file mode 100644
index 0000000000..a624352db9
--- /dev/null
+++ b/boost/endian/detail/endian_store.hpp
@@ -0,0 +1,442 @@
+#ifndef BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED
+#define BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED
+
+// Copyright 2019 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/endian/detail/endian_reverse.hpp>
+#include <boost/endian/detail/order.hpp>
+#include <boost/endian/detail/integral_by_size.hpp>
+#include <boost/endian/detail/is_trivially_copyable.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/static_assert.hpp>
+#include <cstddef>
+#include <cstring>
+
+namespace boost
+{
+namespace endian
+{
+
+namespace detail
+{
+
+template<class T, std::size_t N1, BOOST_SCOPED_ENUM(order) O1, std::size_t N2, BOOST_SCOPED_ENUM(order) O2> struct endian_store_impl
+{
+};
+
+} // namespace detail
+
+// Requires:
+//
+// sizeof(T) must be 1, 2, 4, or 8
+// 1 <= N <= sizeof(T)
+// T is TriviallyCopyable
+// if N < sizeof(T), T is integral or enum
+
+template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) Order>
+inline void endian_store( unsigned char * p, T const & v ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT( sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8 );
+ BOOST_STATIC_ASSERT( N >= 1 && N <= sizeof(T) );
+
+ return detail::endian_store_impl<T, sizeof(T), order::native, N, Order>()( p, v );
+}
+
+namespace detail
+{
+
+// same endianness, same size
+
+template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O> struct endian_store_impl<T, N, O, N, O>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
+
+ std::memcpy( p, &v, N );
+ }
+};
+
+// same size, reverse endianness
+
+template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O1, BOOST_SCOPED_ENUM(order) O2> struct endian_store_impl<T, N, O1, N, O2>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
+
+ typename integral_by_size<N>::type tmp;
+ std::memcpy( &tmp, &v, N );
+
+ endian_reverse_inplace( tmp );
+
+ std::memcpy( p, &tmp, N );
+ }
+};
+
+// truncating store 2 -> 1
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 2, Order, 1, order::little>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 2 ];
+ boost::endian::endian_store<T, 2, order::little>( tmp, v );
+
+ p[0] = tmp[0];
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 2, Order, 1, order::big>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 2 ];
+ boost::endian::endian_store<T, 2, order::big>( tmp, v );
+
+ p[0] = tmp[1];
+ }
+};
+
+// truncating store 4 -> 1
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 1, order::little>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+ boost::endian::endian_store<T, 4, order::little>( tmp, v );
+
+ p[0] = tmp[0];
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 1, order::big>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+ boost::endian::endian_store<T, 4, order::big>( tmp, v );
+
+ p[0] = tmp[3];
+ }
+};
+
+// truncating store 4 -> 2
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 2, order::little>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+ boost::endian::endian_store<T, 4, order::little>( tmp, v );
+
+ p[0] = tmp[0];
+ p[1] = tmp[1];
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 2, order::big>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+ boost::endian::endian_store<T, 4, order::big>( tmp, v );
+
+ p[0] = tmp[2];
+ p[1] = tmp[3];
+ }
+};
+
+// truncating store 4 -> 3
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 3, order::little>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+ boost::endian::endian_store<T, 4, order::little>( tmp, v );
+
+ p[0] = tmp[0];
+ p[1] = tmp[1];
+ p[2] = tmp[2];
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 3, order::big>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 4 ];
+ boost::endian::endian_store<T, 4, order::big>( tmp, v );
+
+ p[0] = tmp[1];
+ p[1] = tmp[2];
+ p[2] = tmp[3];
+ }
+};
+
+// truncating store 8 -> 1
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 1, order::little>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::little>( tmp, v );
+
+ p[0] = tmp[0];
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 1, order::big>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::big>( tmp, v );
+
+ p[0] = tmp[7];
+ }
+};
+
+// truncating store 8 -> 2
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 2, order::little>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::little>( tmp, v );
+
+ p[0] = tmp[0];
+ p[1] = tmp[1];
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 2, order::big>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::big>( tmp, v );
+
+ p[0] = tmp[6];
+ p[1] = tmp[7];
+ }
+};
+
+// truncating store 8 -> 3
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 3, order::little>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::little>( tmp, v );
+
+ p[0] = tmp[0];
+ p[1] = tmp[1];
+ p[2] = tmp[2];
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 3, order::big>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::big>( tmp, v );
+
+ p[0] = tmp[5];
+ p[1] = tmp[6];
+ p[2] = tmp[7];
+ }
+};
+
+// truncating store 8 -> 4
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 4, order::little>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::little>( tmp, v );
+
+ p[0] = tmp[0];
+ p[1] = tmp[1];
+ p[2] = tmp[2];
+ p[3] = tmp[3];
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 4, order::big>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::big>( tmp, v );
+
+ p[0] = tmp[4];
+ p[1] = tmp[5];
+ p[2] = tmp[6];
+ p[3] = tmp[7];
+ }
+};
+
+// truncating store 8 -> 5
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 5, order::little>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::little>( tmp, v );
+
+ p[0] = tmp[0];
+ p[1] = tmp[1];
+ p[2] = tmp[2];
+ p[3] = tmp[3];
+ p[4] = tmp[4];
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 5, order::big>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::big>( tmp, v );
+
+ p[0] = tmp[3];
+ p[1] = tmp[4];
+ p[2] = tmp[5];
+ p[3] = tmp[6];
+ p[4] = tmp[7];
+ }
+};
+
+// truncating store 8 -> 6
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 6, order::little>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::little>( tmp, v );
+
+ p[0] = tmp[0];
+ p[1] = tmp[1];
+ p[2] = tmp[2];
+ p[3] = tmp[3];
+ p[4] = tmp[4];
+ p[5] = tmp[5];
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 6, order::big>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::big>( tmp, v );
+
+ p[0] = tmp[2];
+ p[1] = tmp[3];
+ p[2] = tmp[4];
+ p[3] = tmp[5];
+ p[4] = tmp[6];
+ p[5] = tmp[7];
+ }
+};
+
+// truncating store 8 -> 7
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 7, order::little>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::little>( tmp, v );
+
+ p[0] = tmp[0];
+ p[1] = tmp[1];
+ p[2] = tmp[2];
+ p[3] = tmp[3];
+ p[4] = tmp[4];
+ p[5] = tmp[5];
+ p[6] = tmp[6];
+ }
+};
+
+template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 7, order::big>
+{
+ inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
+
+ unsigned char tmp[ 8 ];
+ boost::endian::endian_store<T, 8, order::big>( tmp, v );
+
+ p[0] = tmp[1];
+ p[1] = tmp[2];
+ p[2] = tmp[3];
+ p[3] = tmp[4];
+ p[4] = tmp[5];
+ p[5] = tmp[6];
+ p[6] = tmp[7];
+ }
+};
+
+} // namespace detail
+
+} // namespace endian
+} // namespace boost
+
+#endif // BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED
diff --git a/boost/endian/detail/integral_by_size.hpp b/boost/endian/detail/integral_by_size.hpp
new file mode 100644
index 0000000000..b0fd8856d9
--- /dev/null
+++ b/boost/endian/detail/integral_by_size.hpp
@@ -0,0 +1,47 @@
+#ifndef BOOST_ENDIAN_DETAIL_INTEGRAL_BY_SIZE_HPP_INCLUDED
+#define BOOST_ENDIAN_DETAIL_INTEGRAL_BY_SIZE_HPP_INCLUDED
+
+// Copyright 2019 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/cstdint.hpp>
+#include <cstddef>
+
+namespace boost
+{
+namespace endian
+{
+namespace detail
+{
+
+template<std::size_t N> struct integral_by_size
+{
+};
+
+template<> struct integral_by_size<1>
+{
+ typedef uint8_t type;
+};
+
+template<> struct integral_by_size<2>
+{
+ typedef uint16_t type;
+};
+
+template<> struct integral_by_size<4>
+{
+ typedef uint32_t type;
+};
+
+template<> struct integral_by_size<8>
+{
+ typedef uint64_t type;
+};
+
+} // namespace detail
+} // namespace endian
+} // namespace boost
+
+#endif // BOOST_ENDIAN_DETAIL_INTEGRAL_BY_SIZE_HPP_INCLUDED
diff --git a/boost/endian/detail/is_trivially_copyable.hpp b/boost/endian/detail/is_trivially_copyable.hpp
new file mode 100644
index 0000000000..334cd462c1
--- /dev/null
+++ b/boost/endian/detail/is_trivially_copyable.hpp
@@ -0,0 +1,39 @@
+#ifndef BOOST_ENDIAN_DETAIL_IS_TRIVIALLY_COPYABLE_HPP_INCLUDED
+#define BOOST_ENDIAN_DETAIL_IS_TRIVIALLY_COPYABLE_HPP_INCLUDED
+
+// Copyright 2019 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/config.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+
+#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
+# include <type_traits>
+#endif
+
+namespace boost
+{
+namespace endian
+{
+namespace detail
+{
+
+#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
+
+using std::is_trivially_copyable;
+
+#else
+
+template<class T> struct is_trivially_copyable: boost::integral_constant<bool,
+ boost::has_trivial_copy<T>::value && boost::has_trivial_assign<T>::value> {};
+
+#endif
+
+} // namespace detail
+} // namespace endian
+} // namespace boost
+
+#endif // BOOST_ENDIAN_DETAIL_IS_TRIVIALLY_COPYABLE_HPP_INCLUDED
diff --git a/boost/endian/detail/lightweight_test.hpp b/boost/endian/detail/lightweight_test.hpp
deleted file mode 100644
index ba0eee2f7c..0000000000
--- a/boost/endian/detail/lightweight_test.hpp
+++ /dev/null
@@ -1,223 +0,0 @@
-// boost/endian/detail/lightweight_test.hpp --------------------------------------------//
-
-#ifndef BOOST_ENDIAN_LIGHTWEIGHT_TEST_HPP
-#define BOOST_ENDIAN_LIGHTWEIGHT_TEST_HPP
-
-// MS compatible compilers support #pragma once
-
-#if defined(_MSC_VER)
-# pragma once
-#endif
-
-//
-// Copyright (c) 2002, 2009, 2014 Peter Dimov
-// Copyright (2) Beman Dawes 2010, 2011, 2015
-// Copyright (3) Ion Gaztanaga 2013
-//
-// Distributed under the Boost Software License, Version 1.0.
-// See http://www.boost.org/LICENSE_1_0.txt
-//
-
-#include <boost/assert.hpp>
-#include <boost/current_function.hpp>
-#include <boost/core/no_exceptions_support.hpp>
-#include <cstring> // for memcmp
-#include <iostream>
-
-// IDE's like Visual Studio perform better if output goes to std::cout or
-// some other stream, so allow user to configure output stream:
-#ifndef BOOST_LIGHTWEIGHT_TEST_OSTREAM
-# define BOOST_LIGHTWEIGHT_TEST_OSTREAM std::cerr
-#endif
-
-namespace boost
-{
-namespace endian
-{
-namespace detail
-{
-
-struct report_errors_reminder
-{
- bool called_report_errors_function;
-
- report_errors_reminder() : called_report_errors_function(false) {}
-
- ~report_errors_reminder()
- {
- BOOST_ASSERT(called_report_errors_function); // verify report_errors() was called
- }
-};
-
-inline report_errors_reminder& report_errors_remind()
-{
- static report_errors_reminder r;
- return r;
-}
-
-inline int & test_errors()
-{
- static int x = 0;
- report_errors_remind();
- return x;
-}
-
-inline void test_failed_impl(char const * expr, char const * file, int line, char const * function)
-{
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): test '" << expr << "' failed in function '"
- << function << "'" << std::endl;
- ++test_errors();
-}
-
-inline void error_impl(char const * msg, char const * file, int line, char const * function)
-{
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): " << msg << " in function '"
- << function << "'" << std::endl;
- ++test_errors();
-}
-
-inline void throw_failed_impl(char const * excep, char const * file, int line, char const * function)
-{
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): Exception '" << excep << "' not thrown in function '"
- << function << "'" << std::endl;
- ++test_errors();
-}
-
-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 )
-{
- if( t == u )
- {
- 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 T, class U> inline void test_ne_impl( char const * expr1, char const * expr2,
- char const * file, int line, char const * function, T const & t, U const & u )
-{
- if( t != u )
- {
- report_errors_remind();
- }
- else
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): test '" << expr1 << " != " << expr2
- << "' failed in function '" << function << "': "
- << "'" << t << "' == '" << u << "'" << std::endl;
- ++test_errors();
- }
-}
-
-template <class T>
-std::string to_hex(const T& x)
-{
- const char hex[] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
- std::string tmp;
- const unsigned char* p = reinterpret_cast<const unsigned char*>(&x);
- const unsigned char* e = p + sizeof(T);
-
- for (; p < e; ++p)
- {
- tmp += hex[*p >> 4]; // high-order nibble
- tmp += hex[*p & 0x0f]; // low-order nibble
- }
- return tmp;
-}
-
-template<class T, class U> inline bool test_memcmp_eq_impl(char const * expr1,
- char const * expr2, char const * file, int line, char const * function, T const & t,
- U const & u)
-{
- BOOST_ASSERT(sizeof(T) == sizeof(U));
- if (sizeof(T) == sizeof(U)
- && std::memcmp(&t, &u, sizeof(T)) == 0)
- {
- report_errors_remind();
- return true;
- }
- else
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << file << "(" << line << "): test 'std::memcmp(" << expr1 << ", " << expr2
- << ") == 0' fails in function '" << function << "': "
- << " with values '" << to_hex(t) << "' and '" << to_hex(u) << "'" << std::endl;
- ++test_errors();
- return false;
- }
-}
-
-} // namespace detail
-
-inline int report_errors()
-{
- boost::endian::detail::report_errors_remind().called_report_errors_function = true;
-
- int errors = boost::endian::detail::test_errors();
-
- if( errors == 0 )
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << "No errors detected." << std::endl;
- return 0;
- }
- else
- {
- BOOST_LIGHTWEIGHT_TEST_OSTREAM
- << errors << " error" << (errors == 1? "": "s") << " detected." << std::endl;
- return 1;
- }
-}
-
-} // namespace endian
-} // namespace boost
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// TODO: Should all test macros return bool? See BOOST_TEST_MEM_EQ usage in fp_exaustive_test,cpp
-//////////////////////////////////////////////////////////////////////////////////////////
-
-
-#define BOOST_TEST(expr) \
- ((expr)? (void)0: ::boost::endian::detail::test_failed_impl(#expr, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION))
-
-#define BOOST_ERROR(msg) \
- ( ::boost::endian::detail::error_impl(msg, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) )
-
-#define BOOST_TEST_EQ(expr1,expr2) \
- ( ::boost::endian::detail::test_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
-#define BOOST_TEST_NE(expr1,expr2) \
- ( ::boost::endian::detail::test_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) )
-
-#define BOOST_TEST_MEM_EQ(expr1,expr2) \
- (::boost::endian::detail::test_memcmp_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2))
-
-#ifndef BOOST_NO_EXCEPTIONS
- #define BOOST_TEST_THROWS( EXPR, EXCEP ) \
- try { \
- EXPR; \
- ::boost::detail::throw_failed_impl \
- (#EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
- } \
- catch(EXCEP const&) { \
- } \
- catch(...) { \
- ::boost::detail::throw_failed_impl \
- (#EXCEP, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \
- } \
- //
-#else
- #define BOOST_TEST_THROWS( EXPR, EXCEP )
-#endif
-
-#endif // #ifndef BOOST_ENDIAN_LIGHTWEIGHT_TEST_HPP
diff --git a/boost/endian/detail/order.hpp b/boost/endian/detail/order.hpp
new file mode 100644
index 0000000000..786be4fd5f
--- /dev/null
+++ b/boost/endian/detail/order.hpp
@@ -0,0 +1,35 @@
+#ifndef BOOST_ENDIAN_DETAIL_ORDER_HPP_INCLUDED
+#define BOOST_ENDIAN_DETAIL_ORDER_HPP_INCLUDED
+
+// Copyright 2019 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/core/scoped_enum.hpp>
+#include <boost/predef/other/endian.h>
+
+namespace boost
+{
+namespace endian
+{
+
+BOOST_SCOPED_ENUM_START(order)
+{
+ big, little,
+
+# if BOOST_ENDIAN_BIG_BYTE
+
+ native = big
+
+# else
+
+ native = little
+
+# endif
+}; BOOST_SCOPED_ENUM_END
+
+} // namespace endian
+} // namespace boost
+
+#endif // BOOST_ENDIAN_DETAIL_ORDER_HPP_INCLUDED
diff --git a/boost/endian/endian.hpp b/boost/endian/endian.hpp
index 6c610c4a9a..06b607bae2 100644
--- a/boost/endian/endian.hpp
+++ b/boost/endian/endian.hpp
@@ -14,6 +14,105 @@
# error "<boost/endian/endian.hpp> is deprecated. Define BOOST_ENDIAN_DEPRECATED_NAMES to use."
#endif
+#include <boost/config/header_deprecated.hpp>
+
+BOOST_HEADER_DEPRECATED( "<boost/endian/arithmetic.hpp>" )
+
#include <boost/endian/arithmetic.hpp>
+#include <boost/config.hpp>
+
+namespace boost
+{
+namespace endian
+{
+ typedef order endianness;
+ typedef align alignment;
+
+# ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES
+ template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits,
+ BOOST_SCOPED_ENUM(align) Align = align::no>
+ using endian = endian_arithmetic<Order, T, n_bits, Align>;
+# endif
+
+ // unaligned big endian signed integer types
+ typedef endian_arithmetic< order::big, int_least8_t, 8 > big8_t;
+ typedef endian_arithmetic< order::big, int_least16_t, 16 > big16_t;
+ typedef endian_arithmetic< order::big, int_least32_t, 24 > big24_t;
+ typedef endian_arithmetic< order::big, int_least32_t, 32 > big32_t;
+ typedef endian_arithmetic< order::big, int_least64_t, 40 > big40_t;
+ typedef endian_arithmetic< order::big, int_least64_t, 48 > big48_t;
+ typedef endian_arithmetic< order::big, int_least64_t, 56 > big56_t;
+ typedef endian_arithmetic< order::big, int_least64_t, 64 > big64_t;
+
+ // unaligned big endian_arithmetic unsigned integer types
+ typedef endian_arithmetic< order::big, uint_least8_t, 8 > ubig8_t;
+ typedef endian_arithmetic< order::big, uint_least16_t, 16 > ubig16_t;
+ typedef endian_arithmetic< order::big, uint_least32_t, 24 > ubig24_t;
+ typedef endian_arithmetic< order::big, uint_least32_t, 32 > ubig32_t;
+ typedef endian_arithmetic< order::big, uint_least64_t, 40 > ubig40_t;
+ typedef endian_arithmetic< order::big, uint_least64_t, 48 > ubig48_t;
+ typedef endian_arithmetic< order::big, uint_least64_t, 56 > ubig56_t;
+ typedef endian_arithmetic< order::big, uint_least64_t, 64 > ubig64_t;
+
+ // unaligned little endian_arithmetic signed integer types
+ typedef endian_arithmetic< order::little, int_least8_t, 8 > little8_t;
+ typedef endian_arithmetic< order::little, int_least16_t, 16 > little16_t;
+ typedef endian_arithmetic< order::little, int_least32_t, 24 > little24_t;
+ typedef endian_arithmetic< order::little, int_least32_t, 32 > little32_t;
+ typedef endian_arithmetic< order::little, int_least64_t, 40 > little40_t;
+ typedef endian_arithmetic< order::little, int_least64_t, 48 > little48_t;
+ typedef endian_arithmetic< order::little, int_least64_t, 56 > little56_t;
+ typedef endian_arithmetic< order::little, int_least64_t, 64 > little64_t;
+
+ // unaligned little endian_arithmetic unsigned integer types
+ typedef endian_arithmetic< order::little, uint_least8_t, 8 > ulittle8_t;
+ typedef endian_arithmetic< order::little, uint_least16_t, 16 > ulittle16_t;
+ typedef endian_arithmetic< order::little, uint_least32_t, 24 > ulittle24_t;
+ typedef endian_arithmetic< order::little, uint_least32_t, 32 > ulittle32_t;
+ typedef endian_arithmetic< order::little, uint_least64_t, 40 > ulittle40_t;
+ typedef endian_arithmetic< order::little, uint_least64_t, 48 > ulittle48_t;
+ typedef endian_arithmetic< order::little, uint_least64_t, 56 > ulittle56_t;
+ typedef endian_arithmetic< order::little, uint_least64_t, 64 > ulittle64_t;
+
+ // unaligned native endian_arithmetic signed integer types
+ typedef endian_arithmetic< order::native, int_least8_t, 8 > native8_t;
+ typedef endian_arithmetic< order::native, int_least16_t, 16 > native16_t;
+ typedef endian_arithmetic< order::native, int_least32_t, 24 > native24_t;
+ typedef endian_arithmetic< order::native, int_least32_t, 32 > native32_t;
+ typedef endian_arithmetic< order::native, int_least64_t, 40 > native40_t;
+ typedef endian_arithmetic< order::native, int_least64_t, 48 > native48_t;
+ typedef endian_arithmetic< order::native, int_least64_t, 56 > native56_t;
+ typedef endian_arithmetic< order::native, int_least64_t, 64 > native64_t;
+
+ // unaligned native endian_arithmetic unsigned integer types
+ typedef endian_arithmetic< order::native, uint_least8_t, 8 > unative8_t;
+ typedef endian_arithmetic< order::native, uint_least16_t, 16 > unative16_t;
+ typedef endian_arithmetic< order::native, uint_least32_t, 24 > unative24_t;
+ typedef endian_arithmetic< order::native, uint_least32_t, 32 > unative32_t;
+ typedef endian_arithmetic< order::native, uint_least64_t, 40 > unative40_t;
+ typedef endian_arithmetic< order::native, uint_least64_t, 48 > unative48_t;
+ typedef endian_arithmetic< order::native, uint_least64_t, 56 > unative56_t;
+ typedef endian_arithmetic< order::native, uint_least64_t, 64 > unative64_t;
+
+ // aligned native endian_arithmetic typedefs are not provided because
+ // <cstdint> types are superior for this use case
+
+ typedef endian_arithmetic< order::big, int16_t, 16, align::yes > aligned_big16_t;
+ typedef endian_arithmetic< order::big, uint16_t, 16, align::yes > aligned_ubig16_t;
+ typedef endian_arithmetic< order::little, int16_t, 16, align::yes > aligned_little16_t;
+ typedef endian_arithmetic< order::little, uint16_t, 16, align::yes > aligned_ulittle16_t;
+
+ typedef endian_arithmetic< order::big, int32_t, 32, align::yes > aligned_big32_t;
+ typedef endian_arithmetic< order::big, uint32_t, 32, align::yes > aligned_ubig32_t;
+ typedef endian_arithmetic< order::little, int32_t, 32, align::yes > aligned_little32_t;
+ typedef endian_arithmetic< order::little, uint32_t, 32, align::yes > aligned_ulittle32_t;
+
+ typedef endian_arithmetic< order::big, int64_t, 64, align::yes > aligned_big64_t;
+ typedef endian_arithmetic< order::big, uint64_t, 64, align::yes > aligned_ubig64_t;
+ typedef endian_arithmetic< order::little, int64_t, 64, align::yes > aligned_little64_t;
+ typedef endian_arithmetic< order::little, uint64_t, 64, align::yes > aligned_ulittle64_t;
+
+} // namespace endian
+} // namespace boost
#endif //BOOST_ENDIAN_ENDIAN_HPP
diff --git a/boost/endian/std_pair.hpp b/boost/endian/std_pair.hpp
deleted file mode 100644
index 8da74b4f70..0000000000
--- a/boost/endian/std_pair.hpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// boost/endian/std_pair.hpp ---------------------------------------------------------//
-
-// Copyright Beman Dawes 2013
-
-// Distributed under the Boost Software License, Version 1.0.
-// http://www.boost.org/LICENSE_1_0.txt
-
-//--------------------------------------------------------------------------------------//
-
-#ifndef BOOST_ENDIAN_STD_PAIR_HPP
-#define BOOST_ENDIAN_STD_PAIR_HPP
-
-#include <boost/endian/conversion.hpp>
-#include <utility>
-
-namespace boost
-{
-namespace endian
-{
- template <class ReversibleValueT, class ReversibleValueU>
- std::pair<ReversibleValueT, ReversibleValueU>
- reverse_value(std::pair<ReversibleValueT, ReversibleValueU> x)
- {
- return std::pair<ReversibleValueT, ReversibleValueU>(reverse_value(x.first),
- reverse_value(x.second));
- }
-
- template <class ReversibleT, class ReversibleU>
- void reverse(std::pair<ReversibleT, ReversibleU>& x)
- {
- reverse(x.first);
- reverse(x.second);
- }
-
-}
-}
-
-#endif // BOOST_ENDIAN_STD_PAIR_HPP
diff --git a/boost/exception/detail/error_info_impl.hpp b/boost/exception/detail/error_info_impl.hpp
index 6c48d61ab3..bef7fd8f7a 100644
--- a/boost/exception/detail/error_info_impl.hpp
+++ b/boost/exception/detail/error_info_impl.hpp
@@ -35,7 +35,7 @@ boost
virtual error_info_base * clone() const = 0;
virtual
- ~error_info_base() throw()
+ ~error_info_base() BOOST_NOEXCEPT_OR_NOTHROW
{
}
};
@@ -46,7 +46,7 @@ boost
error_info:
public exception_detail::error_info_base
{
- error_info_base *
+ exception_detail::error_info_base *
clone() const
{
return new error_info<Tag,T>(*this);
@@ -73,7 +73,7 @@ boost
}
#endif
#endif
- ~error_info() throw()
+ ~error_info() BOOST_NOEXCEPT_OR_NOTHROW
{
}
value_type const &
diff --git a/boost/exception/detail/exception_ptr.hpp b/boost/exception/detail/exception_ptr.hpp
index 8e19f0d9df..a7f0a2507e 100644
--- a/boost/exception/detail/exception_ptr.hpp
+++ b/boost/exception/detail/exception_ptr.hpp
@@ -105,7 +105,7 @@ boost
boost::exception,
std::bad_alloc
{
- ~bad_alloc_() throw() { }
+ ~bad_alloc_() BOOST_NOEXCEPT_OR_NOTHROW { }
};
struct
@@ -113,7 +113,7 @@ boost
boost::exception,
std::bad_exception
{
- ~bad_exception_() throw() { }
+ ~bad_exception_() BOOST_NOEXCEPT_OR_NOTHROW { }
};
template <class Exception>
@@ -174,7 +174,7 @@ boost
add_original_type(e);
}
- ~unknown_exception() throw()
+ ~unknown_exception() BOOST_NOEXCEPT_OR_NOTHROW
{
}
@@ -220,7 +220,7 @@ boost
add_original_type(e1);
}
- ~current_exception_std_exception_wrapper() throw()
+ ~current_exception_std_exception_wrapper() BOOST_NOEXCEPT_OR_NOTHROW
{
}
diff --git a/boost/exception/diagnostic_information.hpp b/boost/exception/diagnostic_information.hpp
index 48f06a0fb9..ad2273573f 100644
--- a/boost/exception/diagnostic_information.hpp
+++ b/boost/exception/diagnostic_information.hpp
@@ -45,6 +45,10 @@ boost
std::exception const * se=current_exception_cast<std::exception const>();
if( be || se )
return exception_detail::diagnostic_information_impl(be,se,true,verbose);
+#if defined(__GLIBCXX__) && __cplusplus >= 201103L && !defined(BOOST_NO_RTTI)
+ else if (auto* p=std::current_exception().__cxa_exception_type())
+ return "Dynamic exception type: "+boost::core::demangle(p->name());
+#endif
else
return "No diagnostic information available.";
}
@@ -157,7 +161,7 @@ boost
core::demangle((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_->name()) << '\n';
#endif
if( with_what && se && verbose )
- tmp << "std::exception::what: " << wh << '\n';
+ tmp << "std::exception::what: " << (wh ? wh : "(null)") << '\n';
if( be )
if( char const * s=exception_detail::get_diagnostic_information(*be,tmp.str().c_str()) )
if( *s )
@@ -175,7 +179,7 @@ boost
inline
char const *
- diagnostic_information_what( exception const & e, bool verbose=true ) throw()
+ diagnostic_information_what( exception const & e, bool verbose=true ) BOOST_NOEXCEPT_OR_NOTHROW
{
char const * w=0;
#ifndef BOOST_NO_EXCEPTIONS
diff --git a/boost/exception/exception.hpp b/boost/exception/exception.hpp
index d5c22c4ca2..ab78767c2b 100644
--- a/boost/exception/exception.hpp
+++ b/boost/exception/exception.hpp
@@ -165,7 +165,7 @@ boost
protected:
- ~error_info_container() throw()
+ ~error_info_container() BOOST_NOEXCEPT_OR_NOTHROW
{
}
};
@@ -233,7 +233,7 @@ boost
#ifdef __HP_aCC
//On HP aCC, this protected copy constructor prevents throwing boost::exception.
//On all other platforms, the same effect is achieved by the pure virtual destructor.
- exception( exception const & x ) throw():
+ exception( exception const & x ) BOOST_NOEXCEPT_OR_NOTHROW:
data_(x.data_),
throw_function_(x.throw_function_),
throw_file_(x.throw_file_),
@@ -242,7 +242,7 @@ boost
}
#endif
- virtual ~exception() throw()
+ virtual ~exception() BOOST_NOEXCEPT_OR_NOTHROW
#ifndef __HP_aCC
= 0 //Workaround for HP aCC, =0 incorrectly leads to link errors.
#endif
@@ -287,7 +287,7 @@ boost
inline
exception::
- ~exception() throw()
+ ~exception() BOOST_NOEXCEPT_OR_NOTHROW
{
}
@@ -337,7 +337,7 @@ boost
{
}
- ~error_info_injector() throw()
+ ~error_info_injector() BOOST_NOEXCEPT_OR_NOTHROW
{
}
};
@@ -398,7 +398,7 @@ boost
virtual void rethrow() const = 0;
virtual
- ~clone_base() throw()
+ ~clone_base() BOOST_NOEXCEPT_OR_NOTHROW
{
}
};
@@ -445,7 +445,7 @@ boost
copy_boost_exception(this,&x);
}
- ~clone_impl() throw()
+ ~clone_impl() BOOST_NOEXCEPT_OR_NOTHROW
{
}
@@ -487,7 +487,7 @@ boost
{
}
- ~wrapexcept() throw()
+ ~wrapexcept() BOOST_NOEXCEPT_OR_NOTHROW
{
}
};
diff --git a/boost/exception/info.hpp b/boost/exception/info.hpp
index f7ac50ecfc..5e3ad52cc6 100644
--- a/boost/exception/info.hpp
+++ b/boost/exception/info.hpp
@@ -62,7 +62,7 @@ boost
{
}
- ~error_info_container_impl() throw()
+ ~error_info_container_impl() BOOST_NOEXCEPT_OR_NOTHROW
{
}
diff --git a/boost/filesystem/path.hpp b/boost/filesystem/path.hpp
index d0cf9a11ca..ad036f19a2 100644
--- a/boost/filesystem/path.hpp
+++ b/boost/filesystem/path.hpp
@@ -536,7 +536,8 @@ namespace path_detail // intentionally don't use filesystem::detail to not bring
bool is_relative() const { return !is_absolute(); }
bool is_absolute() const
{
-# ifdef BOOST_WINDOWS_API
+ // Windows CE has no root name (aka drive letters)
+# if defined(BOOST_WINDOWS_API) && !defined(UNDER_CE)
return has_root_name() && has_root_directory();
# else
return has_root_directory();
@@ -783,7 +784,7 @@ namespace path_detail // intentionally don't use filesystem::detail to not bring
inline bool operator> (const path& lhs, const path& rhs) {return rhs < lhs;}
inline bool operator>=(const path& lhs, const path& rhs) {return !(lhs < rhs);}
- inline std::size_t hash_value(const path& x)
+ inline std::size_t hash_value(const path& x) BOOST_NOEXCEPT
{
# ifdef BOOST_WINDOWS_API
std::size_t seed = 0;
@@ -797,9 +798,18 @@ namespace path_detail // intentionally don't use filesystem::detail to not bring
inline void swap(path& lhs, path& rhs) BOOST_NOEXCEPT { lhs.swap(rhs); }
- inline path operator/(const path& lhs, const path& rhs) { return path(lhs) /= rhs; }
+ inline path operator/(const path& lhs, const path& rhs)
+ {
+ path p = lhs;
+ p /= rhs;
+ return p;
+ }
# if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- inline path&& operator/(path&& lhs, const path& rhs) { lhs /= rhs; return std::move(lhs); }
+ inline path operator/(path&& lhs, const path& rhs)
+ {
+ lhs /= rhs;
+ return std::move(lhs);
+ }
# endif
// inserters and extractors
diff --git a/boost/flyweight/detail/default_value_policy.hpp b/boost/flyweight/detail/default_value_policy.hpp
index 4209a69c1c..e0d9b668bd 100644
--- a/boost/flyweight/detail/default_value_policy.hpp
+++ b/boost/flyweight/detail/default_value_policy.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2006-2014 Joaquin M Lopez Munoz.
+/* Copyright 2006-2019 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)
@@ -39,10 +39,9 @@ struct default_value_policy:value_marker
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)&&\
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)&&\
- BOOST_WORKAROUND(__GNUC__,<=4)&&(__GNUC__<4||__GNUC_MINOR__<=4)
-
-/* GCC 4.4.2 (and probably prior) bug: the default ctor generated by the
- * variadic temmplate ctor below fails to value-initialize x.
+ BOOST_WORKAROUND(BOOST_GCC,<=40603)
+/* GCC bug: the default ctor generated by the variadic template ctor below
+ * fails to value-initialize x.
*/
rep_type():x(){}
diff --git a/boost/foreach.hpp b/boost/foreach.hpp
index eb3a50b653..a87d08df86 100644
--- a/boost/foreach.hpp
+++ b/boost/foreach.hpp
@@ -30,6 +30,13 @@
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
+// Define a compiler generic null pointer value
+#if defined(BOOST_NO_NULLPTR)
+#define BOOST_FOREACH_NULL 0
+#else
+#define BOOST_FOREACH_NULL nullptr
+#endif
+
// Some compilers let us detect even const-qualified rvalues at compile-time
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \
|| defined(BOOST_MSVC) && !defined(_PREFAST_) \
@@ -909,7 +916,7 @@ rderef(auto_any_t cur, type2type<T, C> *)
// A sneaky way to get the type of the collection without evaluating the expression
#define BOOST_FOREACH_TYPEOF(COL) \
- (true ? 0 : boost::foreach_detail_::encode_type(COL, boost::foreach_detail_::is_const_(COL)))
+ (true ? BOOST_FOREACH_NULL : boost::foreach_detail_::encode_type(COL, boost::foreach_detail_::is_const_(COL)))
// returns true_* if the type is noncopyable
#define BOOST_FOREACH_IS_NONCOPYABLE(COL) \
@@ -939,7 +946,7 @@ rderef(auto_any_t cur, type2type<T, C> *)
(COL)
# define BOOST_FOREACH_SHOULD_COPY(COL) \
- (true ? 0 : boost::foreach_detail_::or_( \
+ (true ? BOOST_FOREACH_NULL : boost::foreach_detail_::or_( \
BOOST_FOREACH_IS_RVALUE(COL) \
, BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)))
@@ -962,11 +969,11 @@ rderef(auto_any_t cur, type2type<T, C> *)
// If the type happens to be a lightweight proxy, always make a copy.
# define BOOST_FOREACH_SHOULD_COPY(COL) \
(boost::foreach_detail_::should_copy_impl( \
- true ? 0 : boost::foreach_detail_::or_( \
+ true ? BOOST_FOREACH_NULL : boost::foreach_detail_::or_( \
boost::foreach_detail_::is_array_(COL) \
, BOOST_FOREACH_IS_NONCOPYABLE(COL) \
, boost::foreach_detail_::not_(boost::foreach_detail_::is_const_(COL))) \
- , true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL) \
+ , true ? BOOST_FOREACH_NULL : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL) \
, &BOOST_FOREACH_ID(_foreach_is_rvalue)))
#elif !defined(BOOST_FOREACH_NO_RVALUE_DETECTION)
@@ -985,7 +992,7 @@ rderef(auto_any_t cur, type2type<T, C> *)
// Determine whether the collection expression is an lvalue or an rvalue.
// NOTE: this gets the answer wrong for const rvalues.
# define BOOST_FOREACH_SHOULD_COPY(COL) \
- (true ? 0 : boost::foreach_detail_::or_( \
+ (true ? BOOST_FOREACH_NULL : boost::foreach_detail_::or_( \
boost::foreach_detail_::is_rvalue_((COL), 0) \
, BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)))
@@ -1004,7 +1011,7 @@ rderef(auto_any_t cur, type2type<T, C> *)
// Can't use rvalues with BOOST_FOREACH (unless they are lightweight proxies)
# define BOOST_FOREACH_SHOULD_COPY(COL) \
- (true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL))
+ (true ? BOOST_FOREACH_NULL : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL))
#endif
diff --git a/boost/function/function_base.hpp b/boost/function/function_base.hpp
index 4db31c4fbc..bd0e548bdf 100644
--- a/boost/function/function_base.hpp
+++ b/boost/function/function_base.hpp
@@ -396,16 +396,12 @@ namespace boost {
functor_manager_operation_type op)
{
typedef typename get_function_tag<functor_type>::type tag_type;
- switch (op) {
- case get_functor_type_tag:
+ if (op == get_functor_type_tag) {
out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
- return;
-
- default:
+ } else {
manager(in_buffer, out_buffer, op, tag_type());
- return;
}
}
};
@@ -510,16 +506,12 @@ namespace boost {
functor_manager_operation_type op)
{
typedef typename get_function_tag<functor_type>::type tag_type;
- switch (op) {
- case get_functor_type_tag:
+ if (op == get_functor_type_tag) {
out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
- return;
-
- default:
+ } else {
manager(in_buffer, out_buffer, op, tag_type());
- return;
}
}
};
diff --git a/boost/geometry/algorithms/buffer.hpp b/boost/geometry/algorithms/buffer.hpp
index ec2f9c5aca..6321d9905e 100644
--- a/boost/geometry/algorithms/buffer.hpp
+++ b/boost/geometry/algorithms/buffer.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 2017.
-// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017, 2019.
+// Modifications copyright (c) 2017, 2019 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
@@ -224,7 +224,11 @@ inline void buffer(GeometryIn const& geometry_in,
concepts::check<polygon_type>();
typedef typename point_type<GeometryIn>::type point_type;
- typedef typename rescale_policy_type<point_type>::type rescale_policy_type;
+ typedef typename rescale_policy_type
+ <
+ point_type,
+ typename geometry::cs_tag<point_type>::type
+ >::type rescale_policy_type;
geometry_out.clear();
@@ -244,7 +248,8 @@ inline void buffer(GeometryIn const& geometry_in,
>::type intersection_strategy;
rescale_policy_type rescale_policy
- = boost::geometry::get_rescale_policy<rescale_policy_type>(box);
+ = boost::geometry::get_rescale_policy<rescale_policy_type>(
+ box, intersection_strategy);
detail::buffer::buffer_inserter<polygon_type>(geometry_in, range::back_inserter(geometry_out),
distance_strategy,
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
index 128f2beef3..b21dd4af01 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2016-2018.
-// Modifications copyright (c) 2016-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016-2019.
+// Modifications copyright (c) 2016-2019 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,
@@ -175,7 +175,8 @@ struct buffered_piece_collection
typedef typename geometry::rescale_policy_type
<
- typename geometry::point_type<Ring>::type
+ typename geometry::point_type<Ring>::type,
+ typename IntersectionStrategy::cs_tag
>::type rescale_policy_type;
typedef typename geometry::segment_ratio_type
@@ -483,25 +484,25 @@ struct buffered_piece_collection
// intersection-point -> outgoing)
// for all (co-located) points still present in the map
- for (iterator_type it = boost::begin(m_turns);
- it != boost::end(m_turns);
- ++it)
+ for (iterator_type tit = boost::begin(m_turns);
+ tit != boost::end(m_turns);
+ ++tit)
{
typename occupation_map_type::iterator mit =
- occupation_map.find(it->get_robust_point());
+ occupation_map.find(tit->get_robust_point());
if (mit != occupation_map.end())
{
buffer_occupation_info& info = mit->second;
for (int i = 0; i < 2; i++)
{
- add_incoming_and_outgoing_angles(it->get_robust_point(), *it,
+ add_incoming_and_outgoing_angles(tit->get_robust_point(), *tit,
m_pieces,
- i, it->operations[i].seg_id,
+ i, tit->operations[i].seg_id,
info);
}
- it->count_on_multi++;
+ tit->count_on_multi++;
}
}
@@ -525,10 +526,10 @@ struct buffered_piece_collection
#endif
// Get left turns from all clusters
- for (typename occupation_map_type::iterator it = occupation_map.begin();
- it != occupation_map.end(); ++it)
+ for (typename occupation_map_type::iterator mit = occupation_map.begin();
+ mit != occupation_map.end(); ++mit)
{
- it->second.get_left_turns(it->first, m_turns, m_side_strategy);
+ mit->second.get_left_turns(mit->first, m_turns, m_side_strategy);
}
}
@@ -1419,8 +1420,13 @@ struct buffered_piece_collection
inline void enrich()
{
enrich_intersection_points<false, false, overlay_buffer>(m_turns,
- m_clusters, offsetted_rings, offsetted_rings,
- m_robust_policy, m_side_strategy);
+ m_clusters, offsetted_rings, offsetted_rings,
+ m_robust_policy,
+ m_intersection_strategy.template get_point_in_geometry_strategy
+ <
+ buffered_ring<Ring>,
+ buffered_ring<Ring>
+ >());
}
// Discards all rings which do have not-OK intersection points only.
diff --git a/boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp b/boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp
index 618afe5fba..11f1c689a5 100644
--- a/boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp
+++ b/boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2012-2019 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -10,7 +10,6 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP
-#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/algorithms/detail/buffer/parallel_continue.hpp>
@@ -35,14 +34,19 @@ struct line_line_intersection
static inline strategy::buffer::join_selector apply(Point const& pi, Point const& pj,
Point const& qi, Point const& qj, Point& ip)
{
- // See http://mathworld.wolfram.com/Line-LineIntersection.html
- typedef typename coordinate_type<Point>::type coordinate_type;
+ typedef typename coordinate_type<Point>::type ct;
- coordinate_type const denominator
- = determinant<coordinate_type>(get<0>(pi) - get<0>(pj),
- get<1>(pi) - get<1>(pj),
- get<0>(qi) - get<0>(qj),
- get<1>(qi) - get<1>(qj));
+ // Construct lines in general form (ax + by + c = 0),
+ // (will be replaced by a general_form structure in a next PR)
+ ct const pa = get<1>(pi) - get<1>(pj);
+ ct const pb = get<0>(pj) - get<0>(pi);
+ ct const pc = -pa * get<0>(pi) - pb * get<1>(pi);
+
+ ct const qa = get<1>(qi) - get<1>(qj);
+ ct const qb = get<0>(qj) - get<0>(qi);
+ ct const qc = -qa * get<0>(qi) - qb * get<1>(qi);
+
+ ct const denominator = pb * qa - pa * qb;
// Even if the corner was checked before (so it is convex now), that
// was done on the original geometry. This function runs on the buffered
@@ -51,27 +55,20 @@ struct line_line_intersection
// to check it again.
// For round joins, it will not be used at all.
- // For miter joints, there is a miter limit
+ // For miter joins, there is a miter limit
// If segments are parallel/collinear we must be distinguish two cases:
// they continue each other, or they form a spike
- if (math::equals(denominator, coordinate_type()))
+ ct const zero = ct();
+ if (math::equals(denominator, zero))
{
- return parallel_continue(get<0>(qj) - get<0>(qi),
- get<1>(qj) - get<1>(qi),
- get<0>(pj) - get<0>(pi),
- get<1>(pj) - get<1>(pi))
+ return parallel_continue(qb, -qa, pb, -pa)
? strategy::buffer::join_continue
: strategy::buffer::join_spike
;
}
- coordinate_type d1 = determinant<coordinate_type>(get<0>(pi), get<1>(pi), get<0>(pj), get<1>(pj));
- coordinate_type d2 = determinant<coordinate_type>(get<0>(qi), get<1>(qi), get<0>(qj), get<1>(qj));
-
- double const multiplier = 1.0 / denominator;
-
- set<0>(ip, determinant<coordinate_type>(d1, get<0>(pi) - get<0>(pj), d2, get<0>(qi) - get<0>(qj)) * multiplier);
- set<1>(ip, determinant<coordinate_type>(d1, get<1>(pi) - get<1>(pj), d2, get<1>(qi) - get<1>(qj)) * multiplier);
+ set<0>(ip, (pc * qb - pb * qc) / denominator);
+ set<1>(ip, (pa * qc - pc * qa) / denominator);
return strategy::buffer::join_convex;
}
diff --git a/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
index 26b8684828..a3e99bec71 100644
--- a/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014, 2019, 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
@@ -53,7 +54,15 @@ private:
QueryRangeIterator& qit_min,
Distance& dist_min)
{
- typedef index::rtree<RTreeValueType, index::linear<8> > rtree_type;
+ typedef strategy::index::services::from_strategy
+ <
+ Strategy
+ > index_strategy_from;
+ typedef index::parameters
+ <
+ index::linear<8>, typename index_strategy_from::type
+ > index_parameters_type;
+ typedef index::rtree<RTreeValueType, index_parameters_type> rtree_type;
BOOST_GEOMETRY_ASSERT( rtree_first != rtree_last );
BOOST_GEOMETRY_ASSERT( queries_first != queries_last );
@@ -62,7 +71,9 @@ private:
dist_min = zero;
// create -- packing algorithm
- rtree_type rt(rtree_first, rtree_last);
+ rtree_type rt(rtree_first, rtree_last,
+ index_parameters_type(index::linear<8>(),
+ index_strategy_from::get(strategy)));
RTreeValueType t_v;
bool first = true;
diff --git a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp b/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
index 3e48a05ba9..27174a71bc 100644
--- a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
+++ b/boost/geometry/algorithms/detail/comparable_distance/interface.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 2014.
-// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2019.
+// Modifications copyright (c) 2014, 2019, 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.
@@ -35,9 +36,10 @@ namespace boost { namespace geometry
namespace resolve_strategy
{
+template <typename Strategy>
struct comparable_distance
{
- template <typename Geometry1, typename Geometry2, typename Strategy>
+ template <typename Geometry1, typename Geometry2>
static inline
typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type
apply(Geometry1 const& geometry1,
@@ -59,7 +61,11 @@ struct comparable_distance
Strategy
>::apply(strategy));
}
+};
+template <>
+struct comparable_distance<default_strategy>
+{
template <typename Geometry1, typename Geometry2>
static inline typename comparable_distance_result
<
@@ -101,9 +107,10 @@ struct comparable_distance
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_strategy::comparable_distance::apply(geometry1,
- geometry2,
- strategy);
+ return resolve_strategy::comparable_distance
+ <
+ Strategy
+ >::apply(geometry1, geometry2, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/direction_code.hpp b/boost/geometry/algorithms/detail/direction_code.hpp
index 3a7d3d8789..ab3b1e0a2e 100644
--- a/boost/geometry/algorithms/detail/direction_code.hpp
+++ b/boost/geometry/algorithms/detail/direction_code.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015, 2017.
-// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017, 2019.
+// Modifications copyright (c) 2015-2019 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
@@ -46,14 +46,14 @@ inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
}
-template <typename Point, typename CSTag = typename cs_tag<Point>::type>
+template <typename CSTag>
struct direction_code_impl
{
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_CS, (CSTag));
};
-template <typename Point>
-struct direction_code_impl<Point, cartesian_tag>
+template <>
+struct direction_code_impl<cartesian_tag>
{
template <typename Point1, typename Point2>
static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
@@ -96,8 +96,8 @@ struct direction_code_impl<Point, cartesian_tag>
}
};
-template <typename Point>
-struct direction_code_impl<Point, spherical_equatorial_tag>
+template <>
+struct direction_code_impl<spherical_equatorial_tag>
{
template <typename Point1, typename Point2>
static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
@@ -105,8 +105,8 @@ struct direction_code_impl<Point, spherical_equatorial_tag>
{
typedef typename coordinate_type<Point1>::type coord1_t;
typedef typename coordinate_type<Point2>::type coord2_t;
- typedef typename coordinate_system<Point1>::type::units units_t;
- typedef typename coordinate_system<Point2>::type::units units2_t;
+ typedef typename cs_angular_units<Point1>::type units_t;
+ typedef typename cs_angular_units<Point2>::type units2_t;
BOOST_MPL_ASSERT_MSG((boost::is_same<units_t, units2_t>::value),
NOT_IMPLEMENTED_FOR_DIFFERENT_UNITS,
(units_t, units2_t));
@@ -196,8 +196,8 @@ struct direction_code_impl<Point, spherical_equatorial_tag>
}
};
-template <typename Point>
-struct direction_code_impl<Point, spherical_polar_tag>
+template <>
+struct direction_code_impl<spherical_polar_tag>
{
template <typename Point1, typename Point2>
static inline int apply(Point1 segment_a, Point1 segment_b,
@@ -206,12 +206,12 @@ struct direction_code_impl<Point, spherical_polar_tag>
typedef math::detail::constants_on_spheroid
<
typename coordinate_type<Point1>::type,
- typename coordinate_system<Point1>::type::units
+ typename cs_angular_units<Point1>::type
> constants1;
typedef math::detail::constants_on_spheroid
<
typename coordinate_type<Point2>::type,
- typename coordinate_system<Point2>::type::units
+ typename cs_angular_units<Point2>::type
> constants2;
geometry::set<1>(segment_a,
@@ -223,14 +223,39 @@ struct direction_code_impl<Point, spherical_polar_tag>
return direction_code_impl
<
- Point, spherical_equatorial_tag
+ spherical_equatorial_tag
>::apply(segment_a, segment_b, p);
}
};
-template <typename Point>
-struct direction_code_impl<Point, geographic_tag>
- : direction_code_impl<Point, spherical_equatorial_tag>
+// if spherical_tag is passed then pick cs_tag based on Point1 type
+// with spherical_equatorial_tag as the default
+template <>
+struct direction_code_impl<spherical_tag>
+{
+ template <typename Point1, typename Point2>
+ static inline int apply(Point1 segment_a, Point1 segment_b,
+ Point2 p)
+ {
+ return direction_code_impl
+ <
+ typename boost::mpl::if_c
+ <
+ boost::is_same
+ <
+ typename geometry::cs_tag<Point1>::type,
+ spherical_polar_tag
+ >::value,
+ spherical_polar_tag,
+ spherical_equatorial_tag
+ >::type
+ >::apply(segment_a, segment_b, p);
+ }
+};
+
+template <>
+struct direction_code_impl<geographic_tag>
+ : direction_code_impl<spherical_equatorial_tag>
{};
// Gives sense of direction for point p, collinear w.r.t. segment (a,b)
@@ -238,11 +263,11 @@ struct direction_code_impl<Point, geographic_tag>
// Returns 1 if p goes forward, so extends (a,b)
// Returns 0 if p is equal with b, or if (a,b) is degenerate
// Note that it does not do any collinearity test, that should be done before
-template <typename Point1, typename Point2>
+template <typename CSTag, typename Point1, typename Point2>
inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
Point2 const& p)
{
- return direction_code_impl<Point1>::apply(segment_a, segment_b, p);
+ return direction_code_impl<CSTag>::apply(segment_a, segment_b, p);
}
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 b4c71c8f30..ebf41e896c 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_segment_or_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-2019.
+// Modifications copyright (c) 2013-2019, 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
@@ -21,20 +21,15 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP
-#include <boost/range.hpp>
-#include <boost/geometry/util/range.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp>
-
#include <boost/geometry/geometries/segment.hpp>
-
-#include <boost/geometry/algorithms/not_implemented.hpp>
-
+#include <boost/geometry/util/range.hpp>
#include <boost/geometry/views/closeable_view.hpp>
-#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
-#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
-
namespace boost { namespace geometry
{
@@ -47,6 +42,44 @@ namespace detail { namespace disjoint
template
<
+ typename SegmentOrBox,
+ typename Tag = typename tag<SegmentOrBox>::type
+>
+struct disjoint_point_segment_or_box
+ : not_implemented<Tag>
+{};
+
+template <typename Segment>
+struct disjoint_point_segment_or_box<Segment, segment_tag>
+{
+ template <typename Point, typename Strategy>
+ static inline bool apply(Point const& point, Segment const& segment, Strategy const& strategy)
+ {
+ return dispatch::disjoint
+ <
+ Point, Segment
+ >::apply(point, segment,
+ strategy.template get_point_in_geometry_strategy<Point, Segment>());
+ }
+};
+
+template <typename Box>
+struct disjoint_point_segment_or_box<Box, box_tag>
+{
+ template <typename Point, typename Strategy>
+ static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
+ {
+ return dispatch::disjoint
+ <
+ Point, Box
+ >::apply(point, box,
+ strategy.get_disjoint_point_box_strategy());
+ }
+};
+
+
+template
+<
typename Range,
closure_selector Closure,
typename SegmentOrBox
@@ -83,12 +116,12 @@ struct disjoint_range_segment_or_box
}
else if ( count == 1 )
{
- return dispatch::disjoint
+ return disjoint_point_segment_or_box
<
- point_type, SegmentOrBox
+ SegmentOrBox
>::apply(geometry::range::front<view_type const>(view),
segment_or_box,
- strategy.template get_point_in_geometry_strategy<Range, SegmentOrBox>());
+ strategy);
}
else
{
diff --git a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
index 029d68be5b..58fe2b4fd4 100644
--- a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
@@ -2,7 +2,7 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// Copyright (c) 2014-2018, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -51,16 +51,15 @@ namespace detail { namespace disjoint
{
-template <typename MultiPoint1, typename MultiPoint2>
class multipoint_multipoint
{
private:
- template <typename Iterator>
+ template <typename Iterator, typename CSTag>
class unary_disjoint_predicate
- : geometry::less<>
+ : geometry::less<void, -1, CSTag>
{
private:
- typedef geometry::less<> base_type;
+ typedef geometry::less<void, -1, CSTag> base_type;
public:
unary_disjoint_predicate(Iterator first, Iterator last)
@@ -81,9 +80,14 @@ private:
};
public:
+ template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
static inline bool apply(MultiPoint1 const& multipoint1,
- MultiPoint2 const& multipoint2)
+ MultiPoint2 const& multipoint2,
+ Strategy const&)
{
+ typedef typename Strategy::cs_tag cs_tag;
+ typedef geometry::less<void, -1, cs_tag> less_type;
+
BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) );
typedef typename boost::range_value<MultiPoint1>::type point1_type;
@@ -91,11 +95,12 @@ public:
std::vector<point1_type> points1(boost::begin(multipoint1),
boost::end(multipoint1));
- std::sort(points1.begin(), points1.end(), geometry::less<>());
+ std::sort(points1.begin(), points1.end(), less_type());
typedef unary_disjoint_predicate
<
- typename std::vector<point1_type>::const_iterator
+ typename std::vector<point1_type>::const_iterator,
+ cs_tag
> predicate_type;
return check_iterator_range
@@ -112,12 +117,13 @@ template <typename MultiPoint, typename Linear>
class multipoint_linear
{
private:
+ template <typename ExpandPointBoxStrategy>
struct expand_box_point
{
template <typename Box, typename Point>
static inline void apply(Box& total, Point const& point)
{
- geometry::expand(total, point);
+ geometry::expand(total, point, ExpandPointBoxStrategy());
}
};
@@ -132,7 +138,8 @@ private:
inline void apply(Box& total, Segment const& segment) const
{
geometry::expand(total,
- geometry::return_envelope<Box>(segment, m_strategy));
+ geometry::return_envelope<Box>(segment, m_strategy),
+ typename EnvelopeStrategy::box_expand_strategy_type());
}
EnvelopeStrategy const& m_strategy;
@@ -225,6 +232,7 @@ public:
{
item_visitor_type<Strategy> visitor(strategy);
+ typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type;
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
typedef typename Strategy::disjoint_point_box_strategy_type disjoint_pb_strategy_type;
@@ -238,7 +246,7 @@ public:
<
geometry::model::box<typename point_type<MultiPoint>::type>
>::apply(multipoint, segment_range(linear), visitor,
- expand_box_point(),
+ expand_box_point<expand_point_strategy_type>(),
overlaps_box_point<disjoint_pb_strategy_type>(),
expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
@@ -299,21 +307,23 @@ template <typename MultiPoint, typename MultiGeometry>
class multi_point_multi_geometry
{
private:
+ template <typename ExpandPointStrategy>
struct expand_box_point
{
template <typename Box, typename Point>
static inline void apply(Box& total, Point const& point)
{
- geometry::expand(total, point);
+ geometry::expand(total, point, ExpandPointStrategy());
}
};
+ template <typename ExpandBoxStrategy>
struct expand_box_box_pair
{
template <typename Box, typename BoxPair>
inline void apply(Box& total, BoxPair const& box_pair) const
{
- geometry::expand(total, box_pair.first);
+ geometry::expand(total, box_pair.first, ExpandBoxStrategy());
}
};
@@ -403,10 +413,18 @@ public:
item_visitor_type<Strategy> visitor(multi_geometry, strategy);
+ typedef expand_box_point
+ <
+ typename Strategy::expand_point_strategy_type
+ > expand_box_point_type;
typedef overlaps_box_point
<
typename Strategy::disjoint_point_box_strategy_type
> overlaps_box_point_type;
+ typedef expand_box_box_pair
+ <
+ typename Strategy::envelope_strategy_type::box_expand_strategy_type
+ > expand_box_box_pair_type;
typedef overlaps_box_box_pair
<
typename Strategy::disjoint_box_box_strategy_type
@@ -416,9 +434,9 @@ public:
<
box1_type
>::apply(multi_point, boxes, visitor,
- expand_box_point(),
+ expand_box_point_type(),
overlaps_box_point_type(),
- expand_box_box_pair(),
+ expand_box_box_pair_type(),
overlaps_box_box_pair_type());
return ! visitor.intersection_found();
@@ -493,20 +511,16 @@ struct disjoint
template <typename Strategy>
static inline bool apply(MultiPoint1 const& multipoint1,
MultiPoint2 const& multipoint2,
- Strategy const& )
+ Strategy const& strategy)
{
if ( boost::size(multipoint2) < boost::size(multipoint1) )
{
return detail::disjoint::multipoint_multipoint
- <
- MultiPoint2, MultiPoint1
- >::apply(multipoint2, multipoint1);
+ ::apply(multipoint2, multipoint1, strategy);
}
return detail::disjoint::multipoint_multipoint
- <
- MultiPoint1, MultiPoint2
- >::apply(multipoint1, multipoint2);
+ ::apply(multipoint1, multipoint2, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp b/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
index d6de7cac91..964f3e2189 100644
--- a/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
+++ b/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014, 2019, 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
@@ -165,6 +166,27 @@ private:
}
};
+ template
+ <
+ typename SegOrBox,
+ typename SegOrBoxTag = typename tag<SegOrBox>::type
+ >
+ struct intersects
+ {
+ static inline bool apply(Geometry const& g1, SegOrBox const& g2, Strategy const&)
+ {
+ return geometry::intersects(g1, g2);
+ }
+ };
+
+ template <typename SegOrBox>
+ struct intersects<SegOrBox, segment_tag>
+ {
+ static inline bool apply(Geometry const& g1, SegOrBox const& g2, Strategy const& s)
+ {
+ return geometry::intersects(g1, g2, s.get_relate_segment_segment_strategy());
+ }
+ };
public:
typedef typename strategy::distance::services::return_type
@@ -194,7 +216,7 @@ public:
if (check_intersection
- && geometry::intersects(geometry, segment_or_box))
+ && intersects<SegmentOrBox>::apply(geometry, segment_or_box, strategy))
{
return 0;
}
diff --git a/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp b/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp
index 7b81d68bb4..dfd9d770ee 100644
--- a/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp
+++ b/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014, 2019, 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
@@ -40,7 +41,8 @@ struct linear_to_areal
Areal const& areal,
Strategy const& strategy)
{
- if ( geometry::intersects(linear, areal) )
+ if ( geometry::intersects(linear, areal,
+ strategy.get_relate_segment_segment_strategy()) )
{
return 0;
}
@@ -74,7 +76,8 @@ struct areal_to_areal
Areal2 const& areal2,
Strategy const& strategy)
{
- if ( geometry::intersects(areal1, areal2) )
+ if ( geometry::intersects(areal1, areal2,
+ strategy.get_relate_segment_segment_strategy()) )
{
return 0;
}
diff --git a/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp b/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
index 8f1b33cfb2..da54f20a44 100644
--- a/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
+++ b/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014, 2019, 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
@@ -113,19 +114,21 @@ template <typename MultiPoint, typename Areal, typename Strategy>
class multipoint_to_areal
{
private:
+ template <typename CoveredByStrategy>
struct not_covered_by_areal
{
- not_covered_by_areal(Areal const& areal)
- : m_areal(areal)
+ not_covered_by_areal(Areal const& areal, CoveredByStrategy const& strategy)
+ : m_areal(areal), m_strategy(strategy)
{}
template <typename Point>
inline bool apply(Point const& point) const
{
- return !geometry::covered_by(point, m_areal);
+ return !geometry::covered_by(point, m_areal, m_strategy);
}
Areal const& m_areal;
+ CoveredByStrategy const& m_strategy;
};
public:
@@ -140,11 +143,16 @@ public:
Areal const& areal,
Strategy const& strategy)
{
- not_covered_by_areal predicate(areal);
+ typedef not_covered_by_areal
+ <
+ typename Strategy::point_in_geometry_strategy_type
+ > predicate_type;
+
+ predicate_type predicate(areal, strategy.get_point_in_geometry_strategy());
if (check_iterator_range
<
- not_covered_by_areal, false
+ predicate_type, false
>::apply(boost::begin(multipoint),
boost::end(multipoint),
predicate))
diff --git a/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp b/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp
index f41cf5c764..177eb19f1f 100644
--- a/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp
+++ b/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp
@@ -161,7 +161,8 @@ struct point_to_ring
Strategy const& strategy)
{
// TODO: pass strategy
- if (within::within_point_geometry(point, ring))
+ if (within::within_point_geometry(point, ring,
+ strategy.get_point_in_geometry_strategy()))
{
return return_type(0);
}
@@ -206,7 +207,8 @@ private:
for (InteriorRingIterator it = first; it != last; ++it)
{
// TODO: pass strategy
- if (within::within_point_geometry(point, *it))
+ if (within::within_point_geometry(point, *it,
+ strategy.get_point_in_geometry_strategy()))
{
// the point is inside a polygon hole, so its distance
// to the polygon its distance to the polygon's
@@ -236,7 +238,8 @@ public:
Strategy const& strategy)
{
// TODO: pass strategy
- if (! within::covered_by_point_geometry(point, exterior_ring(polygon)))
+ if (! within::covered_by_point_geometry(point, exterior_ring(polygon),
+ strategy.get_point_in_geometry_strategy()))
{
// the point is outside the exterior ring, so its distance
// to the polygon is its distance to the polygon's exterior ring
@@ -334,7 +337,8 @@ struct point_to_multigeometry<Point, MultiPolygon, Strategy, true>
Strategy const& strategy)
{
// TODO: pass strategy
- if (within::covered_by_point_geometry(point, multipolygon))
+ if (within::covered_by_point_geometry(point, multipolygon,
+ strategy.get_point_in_geometry_strategy()))
{
return 0;
}
diff --git a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
index d88a6699c8..93ebebe18d 100644
--- a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
+++ b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
@@ -542,10 +542,8 @@ private:
SBStrategy const& sb_strategy,
ReturnType& result)
{
- typedef typename geometry::strategy::side::services::default_strategy
- <
- typename geometry::cs_tag<SegmentPoint>::type
- >::type side;
+ typename SBStrategy::side_strategy_type
+ side_strategy = sb_strategy.get_side_strategy();
typedef cast_to_result<ReturnType> cast;
ReturnType diff1 = cast::apply(geometry::get<1>(p1))
@@ -555,12 +553,12 @@ private:
sb_strategy.get_distance_ps_strategy();
int sign = diff1 < 0 ? -1 : 1;
- if (side::apply(p0, p1, corner1) * sign < 0)
+ if (side_strategy.apply(p0, p1, corner1) * sign < 0)
{
result = cast::apply(ps_strategy.apply(corner1, p0, p1));
return true;
}
- if (side::apply(p0, p1, corner2) * sign > 0)
+ if (side_strategy.apply(p0, p1, corner2) * sign > 0)
{
result = cast::apply(ps_strategy.apply(corner2, p0, p1));
return true;
@@ -682,7 +680,7 @@ public:
BoxPoint const& bottom_right,
SBStrategy const& sb_strategy)
{
- BOOST_GEOMETRY_ASSERT( geometry::less<SegmentPoint>()(p0, p1)
+ BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, typename SBStrategy::cs_tag>()(p0, p1))
|| geometry::has_nan_coordinate(p0)
|| geometry::has_nan_coordinate(p1) );
@@ -782,15 +780,9 @@ public:
>,
typename strategy::distance::services::comparable_type
<
- typename detail::distance::default_strategy
- <
- segment_point, Box
- >::type
+ typename SBStrategy::distance_pb_strategy::type
>::type,
- typename detail::distance::default_strategy
- <
- segment_point, Box
- >::type
+ typename SBStrategy::distance_pb_strategy::type
>::type point_box_strategy_type;
return dispatch::distance
@@ -809,7 +801,8 @@ public:
bottom_left, bottom_right,
top_left, top_right);
- if (geometry::less<segment_point>()(p[0], p[1]))
+ typedef geometry::less<segment_point, -1, typename SBStrategy::cs_tag> less_type;
+ if (less_type()(p[0], p[1]))
{
return segment_to_box_2D
<
diff --git a/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp b/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp
index bdf056d76e..55380a3a89 100644
--- a/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp
+++ b/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014, 2019, 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
@@ -70,7 +71,7 @@ public:
apply(Segment1 const& segment1, Segment2 const& segment2,
Strategy const& strategy)
{
- if (geometry::intersects(segment1, segment2))
+ if (geometry::intersects(segment1, segment2, strategy.get_relate_segment_segment_strategy()))
{
return 0;
}
diff --git a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
index 9625f18426..fd5c3caa42 100644
--- a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
+++ b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// 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.
+// This file was modified by Oracle on 2017, 2019.
+// Modifications copyright (c) 2017, 2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -42,13 +42,12 @@
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
+#include <boost/geometry/strategies/normalize.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 side strategy.
@@ -159,7 +158,8 @@ private:
};
// Compatible with spherical_side_formula which currently
-// is the default spherical and geographical strategy
+// is the default spherical_equatorial and geographic strategy
+// so CSTag is spherical_equatorial_tag or geographic_tag
template <typename T, typename Geometry, typename CT, typename CSTag>
struct collected_vector
<
@@ -168,8 +168,8 @@ struct collected_vector
{
typedef T type;
- typedef typename coordinate_system<Geometry>::type cs_type;
- typedef model::point<T, 2, cs_type> point_type;
+ typedef typename geometry::detail::cs_angular_units<Geometry>::type units_type;
+ typedef model::point<T, 2, cs::spherical_equatorial<units_type> > point_type;
typedef model::point<T, 3, cs::cartesian> vector_type;
collected_vector()
@@ -179,7 +179,9 @@ struct collected_vector
collected_vector(Point const& p1, Point const& p2)
: origin(get<0>(p1), get<1>(p1))
{
- origin = detail::return_normalized<point_type>(origin);
+ origin = detail::return_normalized<point_type>(
+ origin,
+ strategy::normalize::spherical_point());
using namespace geometry::formula;
prev = sph_to_cart3d<vector_type>(p1);
@@ -290,7 +292,7 @@ struct collected_vector
private:
template <typename Point>
- Point polar_to_equatorial(Point const& p)
+ Point to_equatorial(Point const& p)
{
typedef typename coordinate_type<Point>::type coord_type;
@@ -309,6 +311,9 @@ private:
};
+// TODO: specialize collected_vector for geographic_tag
+
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace collect_vectors
{
diff --git a/boost/geometry/algorithms/detail/get_left_turns.hpp b/boost/geometry/algorithms/detail/get_left_turns.hpp
index 1fec47a01f..2e0275a9b2 100644
--- a/boost/geometry/algorithms/detail/get_left_turns.hpp
+++ b/boost/geometry/algorithms/detail/get_left_turns.hpp
@@ -247,17 +247,11 @@ inline void block_turns(AngleCollection& sorted, std::size_t cluster_size)
for (typename boost::range_iterator<AngleCollection>::type it = sorted.begin();
it != sorted.end(); ++it)
{
- signed_size_type cluster_index = static_cast<signed_size_type>(it->cluster_index);
- signed_size_type previous_index = cluster_index - 1;
- if (previous_index < 0)
- {
- previous_index = cluster_size - 1;
- }
- signed_size_type next_index = cluster_index + 1;
- if (next_index >= static_cast<signed_size_type>(cluster_size))
- {
- next_index = 0;
- }
+ std::size_t const cluster_index = it->cluster_index;
+ std::size_t const previous_index
+ = cluster_index == 0 ? cluster_size - 1 : cluster_index - 1;
+ std::size_t const next_index
+ = cluster_index + 1 >= cluster_size ? 0 : cluster_index + 1;
if (directions[cluster_index].first
&& directions[cluster_index].second)
diff --git a/boost/geometry/algorithms/detail/has_self_intersections.hpp b/boost/geometry/algorithms/detail/has_self_intersections.hpp
index 1289d946a5..82ace9d0a1 100644
--- a/boost/geometry/algorithms/detail/has_self_intersections.hpp
+++ b/boost/geometry/algorithms/detail/has_self_intersections.hpp
@@ -3,8 +3,8 @@
// 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.
+// This file was modified by Oracle on 2017, 2019.
+// Modifications copyright (c) 2017, 2019 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,
@@ -150,7 +150,7 @@ inline bool has_self_intersections(Geometry const& geometry,
>::type strategy;
rescale_policy_type robust_policy
- = geometry::get_rescale_policy<rescale_policy_type>(geometry);
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry, strategy);
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 0efc9731b5..3a688b9a8b 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, 2017.
-// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2017, 2019.
+// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -109,16 +109,25 @@ struct intersection
<
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)
{
+ typedef typename geometry::rescale_overlay_policy_type
+ <
+ Geometry1,
+ Geometry2,
+ typename Strategy::cs_tag
+ >::type rescale_policy_type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(
+ geometry1, geometry2, strategy);
+
return dispatch::intersection
<
Geometry1,
@@ -131,26 +140,35 @@ struct intersection
<
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
+ typedef typename geometry::rescale_overlay_policy_type
<
- Geometry1, Geometry2
- >::type strategy_type;
+ Geometry1,
+ Geometry2,
+ typename geometry::cs_tag<Geometry1>::type
+ >::type rescale_policy_type;
+ typename strategy::relate::services::default_strategy
+ <
+ Geometry1, Geometry2
+ >::type strategy;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(
+ geometry1, geometry2, strategy);
+
return dispatch::intersection
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, robust_policy, geometry_out,
- strategy_type());
+ strategy);
}
};
@@ -172,19 +190,8 @@ struct intersection
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- 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);
-
return resolve_strategy::intersection::apply(geometry1,
geometry2,
- robust_policy,
geometry_out,
strategy);
}
diff --git a/boost/geometry/algorithms/detail/is_simple/areal.hpp b/boost/geometry/algorithms/detail/is_simple/areal.hpp
index d4d6db9bce..b4eb9fb994 100644
--- a/boost/geometry/algorithms/detail/is_simple/areal.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/areal.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2017, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -35,28 +35,22 @@ namespace detail { namespace is_simple
{
-template <typename Ring>
+template <typename Ring, typename CSTag>
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;
return ! boost::empty(ring)
&& ! detail::is_valid::has_duplicates
<
- Ring, geometry::closure<Ring>::value
+ Ring, geometry::closure<Ring>::value, CSTag
>::apply(ring, policy);
}
};
-template <typename Polygon>
+template <typename Polygon, typename CSTag>
class is_simple_polygon
{
private:
@@ -69,25 +63,21 @@ private:
<
is_simple_ring
<
- typename boost::range_value<InteriorRings>::type
+ typename boost::range_value<InteriorRings>::type,
+ CSTag
>
>::apply(boost::begin(interior_rings),
boost::end(interior_rings));
}
public:
- template <typename Strategy>
- static inline bool apply(Polygon const& polygon, Strategy const&)
- {
- return apply(polygon);
- }
-
static inline bool apply(Polygon const& polygon)
{
return
is_simple_ring
<
- typename ring_type<Polygon>::type
+ typename ring_type<Polygon>::type,
+ CSTag
>::apply(exterior_ring(polygon))
&&
are_simple_interior_rings(geometry::interior_rings(polygon));
@@ -112,8 +102,17 @@ namespace dispatch
// Reference (for polygon validity): OGC 06-103r4 (6.1.11.1)
template <typename Ring>
struct is_simple<Ring, ring_tag>
- : detail::is_simple::is_simple_ring<Ring>
-{};
+{
+ template <typename Strategy>
+ static inline bool apply(Ring const& ring, Strategy const&)
+ {
+ return detail::is_simple::is_simple_ring
+ <
+ Ring,
+ typename Strategy::cs_tag
+ >::apply(ring);
+ }
+};
// A Polygon is always a simple geometric object provided that it is valid.
@@ -121,8 +120,17 @@ struct is_simple<Ring, ring_tag>
// Reference (for validity of Polygons): OGC 06-103r4 (6.1.11.1)
template <typename Polygon>
struct is_simple<Polygon, polygon_tag>
- : detail::is_simple::is_simple_polygon<Polygon>
-{};
+{
+ template <typename Strategy>
+ static inline bool apply(Polygon const& polygon, Strategy const&)
+ {
+ return detail::is_simple::is_simple_polygon
+ <
+ Polygon,
+ typename Strategy::cs_tag
+ >::apply(polygon);
+ }
+};
// Not clear what the definition is.
@@ -140,7 +148,8 @@ struct is_simple<MultiPolygon, multi_polygon_tag>
<
detail::is_simple::is_simple_polygon
<
- typename boost::range_value<MultiPolygon>::type
+ typename boost::range_value<MultiPolygon>::type,
+ typename Strategy::cs_tag
>,
true // allow empty multi-polygon
>::apply(boost::begin(multipolygon), boost::end(multipolygon));
diff --git a/boost/geometry/algorithms/detail/is_simple/linear.hpp b/boost/geometry/algorithms/detail/is_simple/linear.hpp
index e36049a961..57bc295e5d 100644
--- a/boost/geometry/algorithms/detail/is_simple/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/linear.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2017, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -29,7 +29,6 @@
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
-#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
@@ -37,6 +36,7 @@
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
@@ -74,19 +74,25 @@ inline bool check_segment_indices(Turn const& turn,
}
-template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+template
+<
+ typename Geometry,
+ typename EqPPStrategy,
+ typename Tag = typename tag<Geometry>::type
+>
class is_acceptable_turn
: not_implemented<Geometry>
{};
-template <typename Linestring>
-class is_acceptable_turn<Linestring, linestring_tag>
+template <typename Linestring, typename EqPPStrategy>
+class is_acceptable_turn<Linestring, EqPPStrategy, linestring_tag>
{
public:
is_acceptable_turn(Linestring const& linestring)
: m_linestring(linestring)
- , m_is_closed(geometry::equals(range::front(linestring),
- range::back(linestring)))
+ , m_is_closed(geometry::detail::equals::equals_point_point(range::front(linestring),
+ range::back(linestring),
+ EqPPStrategy()))
{}
template <typename Turn>
@@ -104,12 +110,16 @@ private:
bool const m_is_closed;
};
-template <typename MultiLinestring>
-class is_acceptable_turn<MultiLinestring, multi_linestring_tag>
+template <typename MultiLinestring, typename EqPPStrategy>
+class is_acceptable_turn<MultiLinestring, EqPPStrategy, multi_linestring_tag>
{
private:
- typedef typename boost::range_value<MultiLinestring>::type linestring_type;
- typedef is_acceptable_turn<linestring_type> base_type;
+ template <typename Point1, typename Point2>
+ static inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
+ {
+ return geometry::detail::equals::equals_point_point(point1, point2,
+ EqPPStrategy());
+ }
template <typename Point, typename Linestring>
static inline bool is_boundary_point_of(Point const& point,
@@ -117,11 +127,10 @@ private:
{
BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1);
return
- ! geometry::equals(range::front(linestring),
- range::back(linestring))
+ !equals_point_point(range::front(linestring), range::back(linestring))
&&
- (geometry::equals(point, range::front(linestring))
- || geometry::equals(point, range::back(linestring)));
+ (equals_point_point(point, range::front(linestring))
+ || equals_point_point(point, range::back(linestring)));
}
template <typename Turn, typename Linestring>
@@ -134,7 +143,7 @@ private:
&&
check_segment_indices(turn, boost::size(linestring) - 2)
&&
- geometry::equals(range::front(linestring), range::back(linestring))
+ equals_point_point(range::front(linestring), range::back(linestring))
&&
turn.operations[0].fraction.is_zero();
;
@@ -145,13 +154,13 @@ private:
Linestring2 const& ls2)
{
return
- geometry::equals(range::front(ls1), range::front(ls2))
+ equals_point_point(range::front(ls1), range::front(ls2))
?
- geometry::equals(range::back(ls1), range::back(ls2))
+ equals_point_point(range::back(ls1), range::back(ls2))
:
- (geometry::equals(range::front(ls1), range::back(ls2))
+ (equals_point_point(range::front(ls1), range::back(ls2))
&&
- geometry::equals(range::back(ls1), range::front(ls2)))
+ equals_point_point(range::back(ls1), range::front(ls2)))
;
}
@@ -163,6 +172,8 @@ public:
template <typename Turn>
inline bool apply(Turn const& turn) const
{
+ typedef typename boost::range_value<MultiLinestring>::type linestring_type;
+
linestring_type const& ls1 =
range::at(m_multilinestring, turn.operations[0].seg_id.multi_index);
@@ -211,10 +222,16 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg
detail::disjoint::assign_disjoint_policy
> turn_policy;
- is_acceptable_turn<Linear> predicate(linear);
+ typedef is_acceptable_turn
+ <
+ Linear,
+ typename Strategy::equals_point_point_strategy_type
+ > is_acceptable_turn_type;
+
+ is_acceptable_turn_type predicate(linear);
detail::overlay::predicate_based_interrupt_policy
<
- is_acceptable_turn<Linear>
+ is_acceptable_turn_type
> interrupt_policy(predicate);
// TODO: skip_adjacent should be set to false
@@ -245,7 +262,7 @@ struct is_simple_linestring
return ! boost::empty(linestring)
&& ! detail::is_valid::has_duplicates
<
- Linestring, closed
+ Linestring, closed, typename Strategy::cs_tag
>::apply(linestring, policy)
&& ! detail::is_valid::has_spikes
<
diff --git a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
index 61f0bc9130..dfc98041b9 100644
--- a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2017, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -42,19 +42,26 @@ struct is_simple_multipoint
template <typename Strategy>
static inline bool apply(MultiPoint const& multipoint, Strategy const&)
{
+ typedef typename Strategy::cs_tag cs_tag;
+ typedef geometry::less
+ <
+ typename point_type<MultiPoint>::type,
+ -1,
+ cs_tag
+ > less_type;
+
if (boost::empty(multipoint))
{
return true;
}
MultiPoint mp(multipoint);
- std::sort(boost::begin(mp), boost::end(mp),
- geometry::less<typename point_type<MultiPoint>::type>());
+ std::sort(boost::begin(mp), boost::end(mp), less_type());
simplicity_failure_policy policy;
return !detail::is_valid::has_duplicates
<
- MultiPoint, closed
+ MultiPoint, closed, cs_tag
>::apply(mp, policy);
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
index 1d3bda191a..67a94f1016 100644
--- a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 2018, Oracle and/or its affiliates.
+// Copyright (c) 2014, 2018, 2019, 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
@@ -32,7 +32,7 @@ namespace detail { namespace is_valid
{
-template <typename TurnPoint>
+template <typename TurnPoint, typename CSTag>
class complement_graph_vertex
{
public:
@@ -55,7 +55,7 @@ public:
{
return geometry::less
<
- TurnPoint
+ TurnPoint, -1, CSTag
>()(*m_turn_point, *other.m_turn_point);
}
if ( m_turn_point == NULL && other.m_turn_point == NULL )
@@ -77,11 +77,11 @@ private:
-template <typename TurnPoint>
+template <typename TurnPoint, typename CSTag>
class complement_graph
{
private:
- typedef complement_graph_vertex<TurnPoint> vertex;
+ typedef complement_graph_vertex<TurnPoint, CSTag> vertex;
typedef std::set<vertex> vertex_container;
public:
diff --git a/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp b/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp
index 749dd3fc25..5d16e2ea3c 100644
--- a/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 2018, Oracle and/or its affiliates.
+// Copyright (c) 2014, 2018, 2019, 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
@@ -25,10 +25,10 @@ namespace detail { namespace is_valid
#ifdef BOOST_GEOMETRY_TEST_DEBUG
-template <typename OutputStream, typename TurnPoint>
+template <typename OutputStream, typename TurnPoint, typename CSTag>
inline void
debug_print_complement_graph(OutputStream& os,
- complement_graph<TurnPoint> const& graph)
+ complement_graph<TurnPoint, CSTag> const& graph)
{
typedef typename complement_graph<TurnPoint>::vertex_handle vertex_handle;
@@ -58,9 +58,9 @@ debug_print_complement_graph(OutputStream& os,
}
}
#else
-template <typename OutputStream, typename TurnPoint>
+template <typename OutputStream, typename TurnPoint, typename CSTag>
inline void debug_print_complement_graph(OutputStream&,
- complement_graph<TurnPoint> const&)
+ complement_graph<TurnPoint, CSTag> const&)
{
}
#endif
diff --git a/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp b/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp
index 685a4aac35..76dd119f11 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -30,7 +30,7 @@ namespace boost { namespace geometry
namespace detail { namespace is_valid
{
-template <typename Range, closure_selector Closure>
+template <typename Range, closure_selector Closure, typename CSTag>
struct has_duplicates
{
template <typename VisitPolicy>
@@ -51,7 +51,12 @@ struct has_duplicates
return ! visitor.template apply<no_failure>();
}
- geometry::equal_to<typename boost::range_value<Range>::type> equal;
+ geometry::equal_to
+ <
+ typename boost::range_value<Range>::type,
+ -1,
+ CSTag
+ > equal;
const_iterator it = boost::const_begin(view);
const_iterator next = it;
diff --git a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
index 8bb6e3bce1..9f1091ffdb 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2017, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -28,7 +28,7 @@
#include <boost/geometry/views/closeable_view.hpp>
-#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>
#include <boost/geometry/io/dsv/write.hpp>
@@ -42,7 +42,7 @@ namespace boost { namespace geometry
namespace detail { namespace is_valid
{
-template <typename Point>
+template <typename Point, typename Strategy>
struct equal_to
{
Point const& m_point;
@@ -54,11 +54,11 @@ struct equal_to
template <typename OtherPoint>
inline bool operator()(OtherPoint const& other) const
{
- return geometry::equals(m_point, other);
+ return geometry::detail::equals::equals_point_point(m_point, other, Strategy());
}
};
-template <typename Point>
+template <typename Point, typename Strategy>
struct not_equal_to
{
Point const& m_point;
@@ -70,7 +70,7 @@ struct not_equal_to
template <typename OtherPoint>
inline bool operator()(OtherPoint const& other) const
{
- return ! geometry::equals(other, m_point);
+ return ! geometry::detail::equals::equals_point_point(other, m_point, Strategy());
}
};
@@ -79,11 +79,16 @@ struct not_equal_to
template <typename Range, closure_selector Closure>
struct has_spikes
{
- template <typename Iterator>
+ template <typename Iterator, typename SideStrategy>
static inline Iterator find_different_from_first(Iterator first,
- Iterator last)
+ Iterator last,
+ SideStrategy const& )
{
- typedef not_equal_to<typename point_type<Range>::type> not_equal;
+ typedef not_equal_to
+ <
+ typename point_type<Range>::type,
+ typename SideStrategy::equals_point_point_strategy_type
+ > not_equal;
BOOST_GEOMETRY_ASSERT(first != last);
@@ -92,6 +97,37 @@ struct has_spikes
return std::find_if(second, last, not_equal(*first));
}
+ template <typename View, typename VisitPolicy, typename SideStrategy>
+ static inline bool apply_at_closure(View const& view, VisitPolicy& visitor,
+ SideStrategy const& strategy,
+ bool is_linear)
+ {
+ boost::ignore_unused(visitor);
+
+ typedef typename boost::range_iterator<View const>::type iterator;
+
+ iterator cur = boost::begin(view);
+ typename boost::range_reverse_iterator
+ <
+ View const
+ >::type prev = find_different_from_first(boost::rbegin(view),
+ boost::rend(view),
+ strategy);
+
+ iterator next = find_different_from_first(cur, boost::end(view),
+ strategy);
+ if (detail::is_spike_or_equal(*next, *cur, *prev, strategy))
+ {
+ return
+ ! visitor.template apply<failure_spikes>(is_linear, *cur);
+ }
+ else
+ {
+ return ! visitor.template apply<no_failure>();
+ }
+ }
+
+
template <typename VisitPolicy, typename SideStrategy>
static inline bool apply(Range const& range, VisitPolicy& visitor,
SideStrategy const& strategy)
@@ -108,7 +144,7 @@ struct has_spikes
iterator prev = boost::begin(view);
- iterator cur = find_different_from_first(prev, boost::end(view));
+ iterator cur = find_different_from_first(prev, boost::end(view), strategy);
if (cur == boost::end(view))
{
// the range has only one distinct point, so it
@@ -116,7 +152,7 @@ struct has_spikes
return ! visitor.template apply<no_failure>();
}
- iterator next = find_different_from_first(cur, boost::end(view));
+ iterator next = find_different_from_first(cur, boost::end(view), strategy);
if (next == boost::end(view))
{
// the range has only two distinct points, so it
@@ -137,28 +173,14 @@ struct has_spikes
}
prev = cur;
cur = next;
- next = find_different_from_first(cur, boost::end(view));
+ next = find_different_from_first(cur, boost::end(view), strategy);
}
- if (geometry::equals(range::front(view), range::back(view)))
+ if (geometry::detail::equals::
+ equals_point_point(range::front(view), range::back(view),
+ strategy.get_equals_point_point_strategy()))
{
- iterator cur = boost::begin(view);
- typename boost::range_reverse_iterator
- <
- view_type const
- >::type prev = find_different_from_first(boost::rbegin(view),
- boost::rend(view));
-
- iterator next = find_different_from_first(cur, boost::end(view));
- if (detail::is_spike_or_equal(*next, *cur, *prev, strategy))
- {
- return
- ! visitor.template apply<failure_spikes>(is_linear, *cur);
- }
- else
- {
- return ! visitor.template apply<no_failure>();
- }
+ return apply_at_closure(view, visitor, strategy, is_linear);
}
return ! visitor.template apply<no_failure>();
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 82818b0990..1978e83094 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,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2018, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -41,7 +41,7 @@ namespace detail { namespace is_valid
template
<
typename Geometry,
- typename IsAcceptableTurn = is_acceptable_turn<Geometry>
+ typename CSTag
>
class has_valid_self_turns
{
@@ -50,7 +50,8 @@ private:
typedef typename geometry::rescale_policy_type
<
- point_type
+ point_type,
+ CSTag
>::type rescale_policy_type;
typedef detail::overlay::get_turn_info
@@ -79,11 +80,11 @@ public:
boost::ignore_unused(visitor);
rescale_policy_type robust_policy
- = geometry::get_rescale_policy<rescale_policy_type>(geometry);
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry, strategy);
detail::overlay::stateless_predicate_based_interrupt_policy
<
- IsAcceptableTurn
+ is_acceptable_turn<Geometry>
> interrupt_policy;
detail::self_get_turn_points::self_turns<false, turn_policy>(geometry,
diff --git a/boost/geometry/algorithms/detail/is_valid/linear.hpp b/boost/geometry/algorithms/detail/is_valid/linear.hpp
index 39cb36ef5b..edec3ae543 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-2017, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -63,7 +63,11 @@ struct is_valid_linestring
Linestring,
3u,
true,
- not_equal_to<typename point_type<Linestring>::type>
+ not_equal_to
+ <
+ typename point_type<Linestring>::type,
+ typename Strategy::equals_point_point_strategy_type
+ >
>::apply(linestring);
if (num_distinct < 2u)
diff --git a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
index 8fe5803323..e2facb7e37 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-2017, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -119,6 +119,9 @@ private:
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
envelope_strategy_type const envelope_strategy
= strategy.get_envelope_strategy();
+ typedef typename Strategy::disjoint_box_box_strategy_type disjoint_box_box_strategy_type;
+ disjoint_box_box_strategy_type const disjoint_strategy
+ = strategy.get_disjoint_box_box_strategy();
// call partition to check if polygons are disjoint from each other
typename base::template item_visitor_type<Strategy> item_visitor(strategy);
@@ -127,8 +130,15 @@ private:
<
geometry::model::box<typename point_type<MultiPolygon>::type>
>::apply(polygon_iterators, item_visitor,
- typename base::template expand_box<envelope_strategy_type>(envelope_strategy),
- typename base::template overlaps_box<envelope_strategy_type>(envelope_strategy));
+ typename base::template expand_box
+ <
+ envelope_strategy_type
+ >(envelope_strategy),
+ typename base::template overlaps_box
+ <
+ envelope_strategy_type,
+ disjoint_box_box_strategy_type
+ >(envelope_strategy, disjoint_strategy));
if (item_visitor.items_overlap)
{
@@ -283,8 +293,8 @@ public:
{
typedef debug_validity_phase<MultiPolygon> debug_phase;
- if (BOOST_GEOMETRY_CONDITION(
- AllowEmptyMultiGeometries && boost::empty(multipolygon)))
+ if (BOOST_GEOMETRY_CONDITION(AllowEmptyMultiGeometries)
+ && boost::empty(multipolygon))
{
return visitor.template apply<no_failure>();
}
@@ -307,7 +317,7 @@ public:
// compute turns and check if all are acceptable
debug_phase::apply(2);
- typedef has_valid_self_turns<MultiPolygon> has_valid_turns;
+ typedef has_valid_self_turns<MultiPolygon, typename Strategy::cs_tag> has_valid_turns;
std::deque<typename has_valid_turns::turn_type> turns;
bool has_invalid_turns =
diff --git a/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
index 834ce5af2c..90ce2b8982 100644
--- a/boost/geometry/algorithms/detail/is_valid/polygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
@@ -2,7 +2,7 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// Copyright (c) 2014-2018, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -76,7 +76,6 @@ template <typename Polygon, bool CheckRingValidityOnly = false>
class is_valid_polygon
{
protected:
- typedef debug_validity_phase<Polygon> debug_phase;
template <typename VisitPolicy, typename Strategy>
struct per_ring
@@ -121,6 +120,7 @@ protected:
VisitPolicy& visitor,
Strategy const& strategy)
{
+ typedef debug_validity_phase<Polygon> debug_phase;
typedef typename ring_type<Polygon>::type ring_type;
// check validity of exterior ring
@@ -180,29 +180,40 @@ protected:
template <typename EnvelopeStrategy>
struct expand_box
{
- explicit expand_box(EnvelopeStrategy const& strategy) : m_strategy(strategy) {}
+ explicit expand_box(EnvelopeStrategy const& strategy)
+ : m_strategy(strategy)
+ {}
template <typename Box, typename Iterator>
inline void apply(Box& total, partition_item<Iterator, Box> const& item) const
{
- geometry::expand(total, item.get_envelope(m_strategy));
+ geometry::expand(total,
+ item.get_envelope(m_strategy),
+ m_strategy.get_box_expand_strategy());
}
EnvelopeStrategy const& m_strategy;
};
- template <typename EnvelopeStrategy>
+ template <typename EnvelopeStrategy, typename DisjointBoxBoxStrategy>
struct overlaps_box
{
- explicit overlaps_box(EnvelopeStrategy const& strategy) : m_strategy(strategy) {}
+ explicit overlaps_box(EnvelopeStrategy const& envelope_strategy,
+ DisjointBoxBoxStrategy const& disjoint_strategy)
+ : m_envelope_strategy(envelope_strategy)
+ , m_disjoint_strategy(disjoint_strategy)
+ {}
template <typename Box, typename Iterator>
inline bool apply(Box const& box, partition_item<Iterator, Box> const& item) const
{
- return ! geometry::disjoint(item.get_envelope(m_strategy), box);
+ return ! geometry::disjoint(item.get_envelope(m_envelope_strategy),
+ box,
+ m_disjoint_strategy);
}
- EnvelopeStrategy const& m_strategy;
+ EnvelopeStrategy const& m_envelope_strategy;
+ DisjointBoxBoxStrategy const& m_disjoint_strategy;
};
@@ -322,6 +333,9 @@ protected:
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
envelope_strategy_type const envelope_strategy
= strategy.get_envelope_strategy();
+ typedef typename Strategy::disjoint_box_box_strategy_type disjoint_box_box_strategy_type;
+ disjoint_box_box_strategy_type const disjoint_strategy
+ = strategy.get_disjoint_box_box_strategy();
// call partition to check if interior rings are disjoint from
// each other
@@ -331,8 +345,15 @@ protected:
<
box_type
>::apply(ring_iterators, item_visitor,
- expand_box<envelope_strategy_type>(envelope_strategy),
- overlaps_box<envelope_strategy_type>(envelope_strategy));
+ expand_box
+ <
+ envelope_strategy_type
+ >(envelope_strategy),
+ overlaps_box
+ <
+ envelope_strategy_type,
+ disjoint_box_box_strategy_type
+ >(envelope_strategy, disjoint_strategy));
if (item_visitor.items_overlap)
{
@@ -404,7 +425,11 @@ protected:
<
TurnIterator
>::value_type turn_type;
- typedef complement_graph<typename turn_type::point_type> graph;
+ typedef complement_graph
+ <
+ typename turn_type::point_type,
+ typename Strategy::cs_tag
+ > graph;
graph g(geometry::num_interior_rings(polygon) + 1);
for (TurnIterator tit = first; tit != beyond; ++tit)
@@ -451,9 +476,10 @@ public:
}
// compute turns and check if all are acceptable
+ typedef debug_validity_phase<Polygon> debug_phase;
debug_phase::apply(3);
- typedef has_valid_self_turns<Polygon> has_valid_turns;
+ typedef has_valid_self_turns<Polygon, typename Strategy::cs_tag> has_valid_turns;
std::deque<typename has_valid_turns::turn_type> turns;
bool has_invalid_turns
diff --git a/boost/geometry/algorithms/detail/is_valid/ring.hpp b/boost/geometry/algorithms/detail/is_valid/ring.hpp
index 5a55d998e4..2a377ee8cc 100644
--- a/boost/geometry/algorithms/detail/is_valid/ring.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/ring.hpp
@@ -2,7 +2,7 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// Copyright (c) 2014-2018, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -25,13 +25,12 @@
#include <boost/geometry/util/order_as_direction.hpp>
#include <boost/geometry/util/range.hpp>
-#include <boost/geometry/algorithms/equals.hpp>
-
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>
@@ -58,8 +57,8 @@ namespace detail { namespace is_valid
template <typename Ring, closure_selector Closure /* open */>
struct is_topologically_closed
{
- template <typename VisitPolicy>
- static inline bool apply(Ring const&, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename EqPPStrategy>
+ static inline bool apply(Ring const&, VisitPolicy& visitor, EqPPStrategy const&)
{
boost::ignore_unused(visitor);
@@ -70,12 +69,14 @@ struct is_topologically_closed
template <typename Ring>
struct is_topologically_closed<Ring, closed>
{
- template <typename VisitPolicy>
- static inline bool apply(Ring const& ring, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename EqPPStrategy>
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor, EqPPStrategy const&)
{
boost::ignore_unused(visitor);
- if (geometry::equals(range::front(ring), range::back(ring)))
+ if (geometry::detail::equals::equals_point_point(range::front(ring),
+ range::back(ring),
+ EqPPStrategy()))
{
return visitor.template apply<no_failure>();
}
@@ -157,6 +158,8 @@ struct is_valid_ring
static inline bool apply(Ring const& ring, VisitPolicy& visitor,
Strategy const& strategy)
{
+ typedef typename Strategy::cs_tag cs_tag;
+
// return invalid if any of the following condition holds:
// (a) the ring's point coordinates are not invalid (e.g., NaN)
// (b) the ring's size is below the minimal one
@@ -189,7 +192,11 @@ struct is_valid_ring
if (detail::num_distinct_consecutive_points
<
view_type, 4u, true,
- not_equal_to<typename point_type<Ring>::type>
+ not_equal_to
+ <
+ typename point_type<Ring>::type,
+ typename Strategy::equals_point_point_strategy_type
+ >
>::apply(view)
< 4u)
{
@@ -198,11 +205,11 @@ struct is_valid_ring
}
return
- is_topologically_closed<Ring, closure>::apply(ring, visitor)
- && ! has_duplicates<Ring, closure>::apply(ring, visitor)
+ is_topologically_closed<Ring, closure>::apply(ring, visitor, strategy.get_equals_point_point_strategy())
+ && ! has_duplicates<Ring, closure, cs_tag>::apply(ring, visitor)
&& ! has_spikes<Ring, closure>::apply(ring, visitor, strategy.get_side_strategy())
&& (! CheckSelfIntersections
- || has_valid_self_turns<Ring>::apply(ring, visitor, strategy))
+ || has_valid_self_turns<Ring, typename Strategy::cs_tag>::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 30cbf7afdb..244a6ff3b7 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-2017, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -17,8 +17,8 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/assign.hpp>
-#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
@@ -47,6 +47,8 @@ struct is_valid<Segment, segment_tag>
template <typename VisitPolicy, typename Strategy>
static inline bool apply(Segment const& segment, VisitPolicy& visitor, Strategy const&)
{
+ typedef typename Strategy::equals_point_point_strategy_type eq_pp_strategy_type;
+
boost::ignore_unused(visitor);
typename point_type<Segment>::type p[2];
@@ -60,7 +62,8 @@ struct is_valid<Segment, segment_tag>
{
return false;
}
- else if (! geometry::equals(p[0], p[1]))
+ else if (! geometry::detail::equals::equals_point_point(
+ p[0], p[1], eq_pp_strategy_type()))
{
return visitor.template apply<no_failure>();
}
diff --git a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
index 6d3c602ff2..6f36a44fe0 100644
--- a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
+++ b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017, 2018.
-// Modifications copyright (c) 2017-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017, 2018, 2019.
+// Modifications copyright (c) 2017-2019 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,
@@ -125,12 +125,13 @@ struct ring_info_helper
};
+template <typename BoxExpandStrategy>
struct ring_info_helper_get_box
{
template <typename Box, typename InputItem>
static inline void apply(Box& total, InputItem const& item)
{
- geometry::expand(total, item.envelope);
+ geometry::expand(total, item.envelope, BoxExpandStrategy());
}
};
@@ -145,6 +146,7 @@ struct ring_info_helper_ovelaps_box
}
};
+// Segments intersection Strategy
template
<
typename Geometry1,
@@ -190,7 +192,8 @@ struct assign_visitor
{
ring_info_type& inner_in_map = m_ring_map[inner.id];
- if (geometry::covered_by(inner_in_map.point, outer.envelope)
+ if (geometry::covered_by(inner_in_map.point, outer.envelope,
+ typename Strategy::disjoint_point_box_strategy_type())
&& within_selected_input(inner_in_map, inner.id, outer.id,
m_geometry1, m_geometry2, m_collection,
m_strategy)
@@ -329,6 +332,10 @@ inline void assign_parents(Geometry1 const& geometry1,
Strategy
> visitor(geometry1, geometry2, collection, ring_map, strategy, check_for_orientation);
+ typedef ring_info_helper_get_box
+ <
+ typename Strategy::expand_box_strategy_type
+ > expand_box_type;
typedef ring_info_helper_ovelaps_box
<
typename Strategy::disjoint_box_box_strategy_type
@@ -337,8 +344,7 @@ inline void assign_parents(Geometry1 const& geometry1,
geometry::partition
<
box_type
- >::apply(vector, visitor, ring_info_helper_get_box(),
- overlaps_box_type());
+ >::apply(vector, visitor, expand_box_type(), overlaps_box_type());
}
if (check_for_orientation)
diff --git a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
index 287a06b081..d82c34cc77 100644
--- a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017.
-// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017, 2019.
+// Modifications copyright (c) 2017, 2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -53,9 +53,9 @@ namespace detail { namespace overlay
{
template <typename Turns>
-struct discarded_turn
+struct discarded_indexed_turn
{
- discarded_turn(Turns const& turns)
+ discarded_indexed_turn(Turns const& turns)
: m_turns(turns)
{}
@@ -272,7 +272,7 @@ inline void enrich_adapt(Operations& operations, Turns& turns)
}
// Remove discarded turns from operations to avoid having them as next turn
- discarded_turn<Turns> const predicate(turns);
+ discarded_indexed_turn<Turns> const predicate(turns);
operations.erase(std::remove_if(boost::begin(operations),
boost::end(operations), predicate), boost::end(operations));
}
@@ -381,13 +381,13 @@ inline void calculate_remaining_distance(Turns& turns)
\tparam Clusters type of cluster container
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
-\tparam SideStrategy side strategy type
+\tparam PointInGeometryStrategy point in geometry strategy type
\param turns container containing intersection points
\param clusters container containing clusters
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param robust_policy policy to handle robustness issues
-\param strategy strategy
+\param strategy point in geometry strategy
*/
template
<
@@ -397,13 +397,13 @@ template
typename Clusters,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
- typename SideStrategy
+ typename IntersectionStrategy
>
inline void enrich_intersection_points(Turns& turns,
Clusters& clusters,
Geometry1 const& geometry1, Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
- SideStrategy const& strategy)
+ IntersectionStrategy const& strategy)
{
static const detail::overlay::operation_type target_operation
= detail::overlay::operation_from_overlay<OverlayType>::value;
@@ -426,6 +426,15 @@ inline void enrich_intersection_points(Turns& turns,
std::vector<indexed_turn_operation>
> mapped_vector_type;
+ // As long as turn indexes are not used yet, turns might be erased from
+ // the vector
+ // For now start turns are disabled.
+ // TODO: remove code or fix inconsistencies within validity and relations
+ // detail::overlay::erase_colocated_start_turns(turns, geometry1, geometry2);
+
+ // From here on, turn indexes are used (in clusters, next_index, etc)
+ // and may only be flagged as discarded
+
bool has_cc = false;
bool const has_colocations
= detail::overlay::handle_colocations<Reverse1, Reverse2, OverlayType>(turns,
@@ -472,14 +481,16 @@ inline void enrich_intersection_points(Turns& turns,
{
detail::overlay::discard_closed_turns
<
- OverlayType,
- target_operation
- >::apply(turns, clusters, geometry1, geometry2);
+ OverlayType,
+ target_operation
+ >::apply(turns, clusters, geometry1, geometry2,
+ strategy);
detail::overlay::discard_open_turns
<
OverlayType,
target_operation
- >::apply(turns, clusters, geometry1, geometry2);
+ >::apply(turns, clusters, geometry1, geometry2,
+ strategy);
}
// Create a map of vectors of indexed operation-types to be able
@@ -502,7 +513,7 @@ inline void enrich_intersection_points(Turns& turns,
detail::overlay::enrich_sort<Reverse1, Reverse2>(
mit->second, turns,
geometry1, geometry2,
- robust_policy, strategy);
+ robust_policy, strategy.get_side_strategy());
}
for (typename mapped_vector_type::iterator mit
@@ -532,7 +543,7 @@ inline void enrich_intersection_points(Turns& turns,
Reverse2,
OverlayType
>(clusters, turns, target_operation,
- geometry1, geometry2, strategy);
+ geometry1, geometry2, strategy.get_side_strategy());
detail::overlay::cleanup_clusters(turns, clusters);
}
diff --git a/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp b/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp
new file mode 100644
index 0000000000..a306cb4421
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp
@@ -0,0 +1,174 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2019 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+#include <cmath>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename T>
+struct distance_measure
+{
+ T measure;
+
+ distance_measure()
+ : measure(T())
+ {}
+
+ bool is_small() const { return true; }
+ bool is_zero() const { return true; }
+ bool is_positive() const { return false; }
+ bool is_negative() const { return false; }
+};
+
+template <typename T>
+struct distance_measure_floating
+{
+ T measure;
+
+ distance_measure_floating()
+ : measure(T())
+ {}
+
+ // Returns true if the distance measure is small.
+ // This is an arbitrary boundary, to enable some behaviour
+ // (for example include or exclude turns), which are checked later
+ // with other conditions.
+ bool is_small() const { return std::abs(measure) < 1.0e-3; }
+
+ // Returns true if the distance measure is absolutely zero
+ bool is_zero() const { return measure == 0.0; }
+
+ // Returns true if the distance measure is positive. Distance measure
+ // algorithm returns positive value if it is located on the left side.
+ bool is_positive() const { return measure > 0.0; }
+
+ // Returns true if the distance measure is negative. Distance measure
+ // algorithm returns negative value if it is located on the right side.
+ bool is_negative() const { return measure < 0.0; }
+};
+
+template <>
+struct distance_measure<long double>
+ : public distance_measure_floating<long double> {};
+
+template <>
+struct distance_measure<double>
+ : public distance_measure_floating<double> {};
+
+template <>
+struct distance_measure<float>
+ : public distance_measure_floating<float> {};
+
+} // detail
+
+
+namespace detail_dispatch
+{
+
+// TODO: this is effectively a strategy, but for internal usage.
+// It might be moved to the strategies folder.
+
+template <typename CalculationType, typename CsTag>
+struct get_distance_measure
+ : not_implemented<CsTag>
+{};
+
+template <typename CalculationType>
+struct get_distance_measure<CalculationType, cartesian_tag>
+{
+ typedef detail::distance_measure<CalculationType> result_type;
+
+ template <typename SegmentPoint, typename Point>
+ static result_type apply(SegmentPoint const& p1, SegmentPoint const& p2,
+ Point const& p)
+ {
+ typedef CalculationType ct;
+
+ // Construct a line in general form (ax + by + c = 0),
+ // (will be replaced by a general_form structure in next PR)
+ ct const x1 = geometry::get<0>(p1);
+ ct const y1 = geometry::get<1>(p1);
+ ct const x2 = geometry::get<0>(p2);
+ ct const y2 = geometry::get<1>(p2);
+ ct const a = y1 - y2;
+ ct const b = x2 - x1;
+ ct const c = -a * x1 - b * y1;
+
+ // Returns a distance measure
+ // https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_an_equation
+ // dividing by sqrt(a*a+b*b) is not necessary for this distance measure,
+ // it is not a real distance and purpose is to detect small differences
+ // in collinearity
+ result_type result;
+ result.measure = a * geometry::get<0>(p) + b * geometry::get<1>(p) + c;
+
+ return result;
+ }
+};
+
+template <typename CalculationType>
+struct get_distance_measure<CalculationType, spherical_tag>
+{
+ typedef detail::distance_measure<CalculationType> result_type;
+
+ template <typename SegmentPoint, typename Point>
+ static result_type apply(SegmentPoint const& , SegmentPoint const& ,
+ Point const& )
+ {
+ // TODO, optional
+ result_type result;
+ return result;
+ }
+};
+
+template <typename CalculationType>
+struct get_distance_measure<CalculationType, geographic_tag>
+ : get_distance_measure<CalculationType, spherical_tag> {};
+
+
+} // namespace detail_dispatch
+
+namespace detail
+{
+
+// Returns a (often very tiny) value to indicate its side, and distance,
+// 0 (absolutely 0, not even an epsilon) means collinear. Like side,
+// a negative means that p is to the right of p1-p2. And a positive value
+// means that p is to the left of p1-p2.
+
+template <typename cs_tag, typename SegmentPoint, typename Point>
+static distance_measure<typename select_coordinate_type<SegmentPoint, Point>::type>
+get_distance_measure(SegmentPoint const& p1, SegmentPoint const& p2, Point const& p)
+{
+ return detail_dispatch::get_distance_measure
+ <
+ typename select_coordinate_type<SegmentPoint, Point>::type,
+ cs_tag
+ >::apply(p1, p2, p);
+
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/get_ring.hpp b/boost/geometry/algorithms/detail/overlay/get_ring.hpp
index 460c30def3..07e984b194 100644
--- a/boost/geometry/algorithms/detail/overlay/get_ring.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_ring.hpp
@@ -18,6 +18,8 @@
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/range.hpp>
@@ -49,8 +51,6 @@ struct get_ring<void>
};
-
-
template<>
struct get_ring<ring_tag>
{
@@ -113,6 +113,17 @@ struct get_ring<multi_polygon_tag>
};
+template <typename Geometry>
+inline std::size_t segment_count_on_ring(Geometry const& geometry,
+ segment_identifier const& seg_id)
+{
+ typedef typename geometry::tag<Geometry>::type tag;
+ ring_identifier const rid(0, seg_id.multi_index, seg_id.ring_index);
+ // A closed polygon, a triangle of 4 points, including starting point,
+ // contains 3 segments. So handle as if closed and subtract one.
+ return geometry::num_points(detail::overlay::get_ring<tag>::apply(rid, geometry), true) - 1;
+}
+
}} // namespace detail::overlay
#endif // DOXYGEN_NO_DETAIL
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
index 6d92b1bd3c..c6429bc558 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
@@ -21,11 +21,12 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/config.hpp>
#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
-#include <boost/geometry/algorithms/detail/recalculate.hpp>
#include <boost/geometry/geometries/segment.hpp>
@@ -142,6 +143,72 @@ struct base_turn_handler
ctype const dy = get<1>(a) - get<1>(b);
return dx * dx + dy * dy;
}
+
+ template
+ <
+ std::size_t IndexP,
+ std::size_t IndexQ,
+ typename UniqueSubRange1,
+ typename UniqueSubRange2,
+ typename UmbrellaStrategy,
+ typename TurnInfo
+ >
+ static inline void both_collinear(
+ UniqueSubRange1 const& range_p,
+ UniqueSubRange2 const& range_q,
+ UmbrellaStrategy const&,
+ std::size_t index_p, std::size_t index_q,
+ TurnInfo& ti)
+ {
+ boost::ignore_unused(range_p, range_q);
+ BOOST_GEOMETRY_ASSERT(IndexP + IndexQ == 1);
+ BOOST_GEOMETRY_ASSERT(index_p > 0 && index_p <= 2);
+ BOOST_GEOMETRY_ASSERT(index_q > 0 && index_q <= 2);
+
+#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
+ ti.operations[IndexP].remaining_distance = distance_measure(ti.point, range_p.at(index_p));
+ ti.operations[IndexQ].remaining_distance = distance_measure(ti.point, range_q.at(index_q));
+
+ // pk/q2 is considered as collinear, but there might be
+ // a tiny measurable difference. If so, use that.
+ // Calculate pk // qj-qk
+ typedef detail::distance_measure
+ <
+ typename select_coordinate_type
+ <
+ typename UniqueSubRange1::point_type,
+ typename UniqueSubRange2::point_type
+ >::type
+ > dm_type;
+
+ const bool p_closer =
+ ti.operations[IndexP].remaining_distance
+ < ti.operations[IndexQ].remaining_distance;
+ dm_type const dm
+ = p_closer
+ ? get_distance_measure<typename UmbrellaStrategy::cs_tag>(range_q.at(index_q - 1),
+ range_q.at(index_q), range_p.at(index_p))
+ : get_distance_measure<typename UmbrellaStrategy::cs_tag>(range_p.at(index_p - 1),
+ range_p.at(index_p), range_q.at(index_q));
+
+ if (! dm.is_zero())
+ {
+ // Not truely collinear, distinguish for union/intersection
+ // If p goes left (positive), take that for a union
+
+ bool p_left = p_closer ? dm.is_positive() : dm.is_negative();
+
+ ti.operations[IndexP].operation = p_left
+ ? operation_union : operation_intersection;
+ ti.operations[IndexQ].operation = p_left
+ ? operation_intersection : operation_union;
+ return;
+ }
+#endif
+
+ both(ti, operation_continue);
+ }
+
};
@@ -159,14 +226,16 @@ struct touch_interior : public base_turn_handler
typename UniqueSubRange2,
typename IntersectionInfo,
typename DirInfo,
- typename SidePolicy
+ typename SidePolicy,
+ typename UmbrellaStrategy
>
static inline void apply(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
TurnInfo& ti,
IntersectionInfo const& intersection_info,
DirInfo const& dir_info,
- SidePolicy const& side)
+ SidePolicy const& side,
+ UmbrellaStrategy const& umbrella_strategy)
{
assign_point(ti, method_touch_interior, intersection_info, 0);
@@ -266,19 +335,8 @@ struct touch_interior : public base_turn_handler
// Q intersects on interior of P and continues collinearly
if (side_qk_q == side_qi_p)
{
- // Collinearly in the same direction
- // (Q comes from left of P and turns left,
- // OR Q comes from right of P and turns right)
- // Omit second intersection point.
- // Union: just continue
- // Intersection: just continue
- both(ti, operation_continue);
-
- // Calculate remaining distance.
- // Q arrives at p, at point qj, so use qk for q
- // and use pj for p
- ti.operations[index_p].remaining_distance = distance_measure(ti.point, range_p.at(1));
- ti.operations[index_q].remaining_distance = distance_measure(ti.point, range_q.at(2));
+ both_collinear<index_p, index_q>(range_p, range_q, umbrella_strategy, 1, 2, ti);
+ return;
}
else
{
@@ -326,14 +384,16 @@ struct touch : public base_turn_handler
typename UniqueSubRange2,
typename IntersectionInfo,
typename DirInfo,
- typename SidePolicy
+ typename SideCalculator,
+ typename UmbrellaStrategy
>
static inline void apply(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
TurnInfo& ti,
IntersectionInfo const& intersection_info,
DirInfo const& dir_info,
- SidePolicy const& side)
+ SideCalculator const& side,
+ UmbrellaStrategy const& umbrella_strategy)
{
assign_point(ti, method_touch, intersection_info, 0);
@@ -369,13 +429,12 @@ struct touch : public base_turn_handler
// (#BRL2)
if (side_pk_q2 == 0 && ! block_q)
{
- both(ti, operation_continue);
+ both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti);
return;
}
int const side_pk_q1 = has_pk && has_qk ? side.pk_wrt_q1() : 0;
-
// Collinear opposite case -> block P
// (#BRL4, #BLR8)
if (side_pk_q1 == 0)
@@ -513,14 +572,16 @@ struct equal : public base_turn_handler
typename UniqueSubRange2,
typename IntersectionInfo,
typename DirInfo,
- typename SidePolicy
+ typename SideCalculator,
+ typename UmbrellaStrategy
>
static inline void apply(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
TurnInfo& ti,
IntersectionInfo const& info,
DirInfo const& ,
- SidePolicy const& side)
+ SideCalculator const& side,
+ UmbrellaStrategy const& umbrella_strategy)
{
// Copy the intersection point in TO direction
assign_point(ti, method_equal, info, non_opposite_to_index(info));
@@ -538,8 +599,7 @@ struct equal : public base_turn_handler
// oppositely
if (side_pk_q2 == 0 && side_pk_p == side_qk_p)
{
- both(ti, operation_continue);
-
+ both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti);
return;
}
@@ -562,6 +622,132 @@ struct equal : public base_turn_handler
template
<
+ typename TurnInfo
+>
+struct start : public base_turn_handler
+{
+ template
+ <
+ typename UniqueSubRange1,
+ typename UniqueSubRange2,
+ typename IntersectionInfo,
+ typename DirInfo,
+ typename SideCalculator,
+ typename UmbrellaStrategy
+ >
+ static inline bool apply(UniqueSubRange1 const& range_p,
+ UniqueSubRange2 const& range_q,
+ TurnInfo& ti,
+ IntersectionInfo const& info,
+ DirInfo const& dir_info,
+ SideCalculator const& side,
+ UmbrellaStrategy const& )
+ {
+ // For now disabled. TODO: remove all code or fix inconsistencies
+ // within validity and relations
+ return false;
+
+ if (dir_info.opposite)
+ {
+ // They should not be collinear
+ return false;
+ }
+
+ int const side_pj_q1 = side.pj_wrt_q1();
+ int const side_qj_p1 = side.qj_wrt_p1();
+
+ // Get side values at starting point
+ typedef detail::distance_measure
+ <
+ typename select_coordinate_type
+ <
+ typename UniqueSubRange1::point_type,
+ typename UniqueSubRange2::point_type
+ >::type
+ > dm_type;
+
+ typedef typename UmbrellaStrategy::cs_tag cs_tag;
+ dm_type const dm_pi_q1 = get_distance_measure<cs_tag>(range_q.at(0), range_q.at(1), range_p.at(0));
+ dm_type const dm_qi_p1 = get_distance_measure<cs_tag>(range_p.at(0), range_p.at(1), range_q.at(0));
+
+ if (dir_info.how_a == -1 && dir_info.how_b == -1)
+ {
+ // Both p and q leave
+ if (dm_pi_q1.is_zero() && dm_qi_p1.is_zero())
+ {
+ // Exactly collinear, not necessary to handle it
+ return false;
+ }
+
+ if (! (dm_pi_q1.is_small() && dm_qi_p1.is_small()))
+ {
+ // Not nearly collinear
+ return false;
+ }
+
+ if (side_qj_p1 == 0)
+ {
+ // Collinear is not handled
+ return false;
+ }
+
+ ui_else_iu(side_qj_p1 == -1, ti);
+ }
+ else if (dir_info.how_b == -1)
+ {
+ // p --------------->
+ // |
+ // | q q leaves
+ // v
+ //
+
+ if (dm_qi_p1.is_zero() || ! dm_qi_p1.is_small())
+ {
+ // Exactly collinear
+ return false;
+ }
+
+ if (side_qj_p1 == 0)
+ {
+ // Collinear is not handled
+ return false;
+ }
+
+ ui_else_iu(side_qj_p1 == -1, ti);
+ }
+ else if (dir_info.how_a == -1)
+ {
+ if (dm_pi_q1.is_zero() || ! dm_pi_q1.is_small())
+ {
+ // It starts exactly, not necessary to handle it
+ return false;
+ }
+
+ // p leaves
+ if (side_pj_q1 == 0)
+ {
+ // Collinear is not handled
+ return false;
+ }
+
+ ui_else_iu(side_pj_q1 == 1, ti);
+ }
+ else
+ {
+ // Not supported
+ return false;
+ }
+
+ // Copy intersection point
+ assign_point(ti, method_start, info, 0);
+ return true;
+ }
+
+};
+
+
+template
+<
typename TurnInfo,
typename AssignPolicy
>
@@ -950,7 +1136,7 @@ struct get_turn_info
typename UniqueSubRange1,
typename UniqueSubRange2,
typename TurnInfo,
- typename IntersectionStrategy,
+ typename UmbrellaStrategy,
typename RobustPolicy,
typename OutputIterator
>
@@ -958,7 +1144,7 @@ struct get_turn_info
UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
TurnInfo const& tp_model,
- IntersectionStrategy const& intersection_strategy,
+ UmbrellaStrategy const& umbrella_strategy,
RobustPolicy const& robust_policy,
OutputIterator out)
{
@@ -966,30 +1152,24 @@ struct get_turn_info
<
UniqueSubRange1, UniqueSubRange2,
typename TurnInfo::point_type,
- IntersectionStrategy,
+ UmbrellaStrategy,
RobustPolicy
> inters_info;
- inters_info inters(range_p, range_q,
- intersection_strategy, robust_policy);
+ inters_info inters(range_p, range_q, umbrella_strategy, robust_policy);
char const method = inters.d_info().how;
// Copy, to copy possibly extended fields
TurnInfo tp = tp_model;
+ bool do_only_convert = false;
+
// Select method and apply
switch(method)
{
- case 'a' : // collinear, "at"
- case 'f' : // collinear, "from"
- case 's' : // starts from the middle
- if (AssignPolicy::include_no_turn
- && inters.i_info().count > 0)
- {
- only_convert::apply(tp, inters.i_info());
- *out++ = tp;
- }
+ case 'a' : // "angle"
+ do_only_convert = true;
break;
case 'd' : // disjoint: never do anything
@@ -1000,19 +1180,19 @@ struct get_turn_info
typedef touch_interior
<
TurnInfo
- > policy;
+ > handler;
// If Q (1) arrives (1)
if ( inters.d_info().arrival[1] == 1 )
{
- policy::template apply<0>(range_p, range_q, tp, inters.i_info(), inters.d_info(),
- inters.sides());
+ handler::template apply<0>(range_p, range_q, tp, inters.i_info(), inters.d_info(),
+ inters.sides(), umbrella_strategy);
}
else
{
// Swap p/q
- policy::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(),
- inters.get_swapped_sides());
+ handler::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(),
+ inters.get_swapped_sides(), umbrella_strategy);
}
*out++ = tp;
}
@@ -1026,17 +1206,31 @@ struct get_turn_info
case 't' :
{
// Both touch (both arrive there)
- touch<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides());
+ touch<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy);
*out++ = tp;
}
break;
+ case 'f' :
+ case 's' :
+ {
+ // "from" or "start" without rescaling, it is in some cases necessary to handle
+ if (start<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy))
+ {
+ *out++ = tp;
+ }
+ else
+ {
+ do_only_convert = true;
+ }
+ }
+ break;
case 'e':
{
if ( ! inters.d_info().opposite )
{
// Both equal
// or collinear-and-ending at intersection point
- equal<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides());
+ equal<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy);
*out++ = tp;
}
else
@@ -1059,7 +1253,7 @@ struct get_turn_info
{
// Collinear, but similar thus handled as equal
equal<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(), inters.sides());
+ inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy);
// override assigned method
tp.method = method_collinear;
@@ -1105,6 +1299,14 @@ struct get_turn_info
break;
}
+ if (do_only_convert
+ && AssignPolicy::include_no_turn
+ && inters.i_info().count > 0)
+ {
+ only_convert::apply(tp, inters.i_info());
+ *out++ = tp;
+ }
+
return out;
}
};
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 087ca80602..4788118601 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
-// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019.
+// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -217,7 +217,7 @@ private :
template
<
typename UniqueSubRange1, typename UniqueSubRange2,
- typename TurnPoint, typename IntersectionStrategy, typename RobustPolicy>
+ typename TurnPoint, typename UmbrellaStrategy, typename RobustPolicy>
class intersection_info_base
: private robust_points<UniqueSubRange1, UniqueSubRange2, RobustPolicy>
{
@@ -232,7 +232,7 @@ public:
typedef typename cs_tag<TurnPoint>::type cs_tag;
- typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
+ typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type;
typedef side_calculator<cs_tag, robust_subrange1, robust_subrange2,
side_strategy_type> side_calculator_type;
@@ -244,7 +244,7 @@ public:
intersection_info_base(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
- IntersectionStrategy const& intersection_strategy,
+ UmbrellaStrategy const& umbrella_strategy,
RobustPolicy const& robust_policy)
: base(range_p, range_q, robust_policy)
, m_range_p(range_p)
@@ -252,7 +252,7 @@ public:
, m_robust_range_p(range_p, base::m_rpi, base::m_rpj, robust_policy)
, m_robust_range_q(range_q, base::m_rqi, base::m_rqj, robust_policy)
, m_side_calc(m_robust_range_p, m_robust_range_q,
- intersection_strategy.get_side_strategy())
+ umbrella_strategy.get_side_strategy())
{}
inline typename UniqueSubRange1::point_type const& pi() const { return m_range_p.at(0); }
@@ -289,10 +289,10 @@ private :
template
<
typename UniqueSubRange1, typename UniqueSubRange2,
- typename TurnPoint, typename IntersectionStrategy
+ typename TurnPoint, typename UmbrellaStrategy
>
class intersection_info_base<UniqueSubRange1, UniqueSubRange2,
- TurnPoint, IntersectionStrategy, detail::no_rescale_policy>
+ TurnPoint, UmbrellaStrategy, detail::no_rescale_policy>
{
public:
typedef typename UniqueSubRange1::point_type point1_type;
@@ -301,9 +301,9 @@ public:
typedef typename UniqueSubRange1::point_type robust_point1_type;
typedef typename UniqueSubRange2::point_type robust_point2_type;
- typedef typename cs_tag<TurnPoint>::type cs_tag;
+ typedef typename UmbrellaStrategy::cs_tag cs_tag;
- typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
+ typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type;
typedef side_calculator<cs_tag, UniqueSubRange1, UniqueSubRange2, side_strategy_type> side_calculator_type;
typedef side_calculator
@@ -314,12 +314,12 @@ public:
intersection_info_base(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
- IntersectionStrategy const& intersection_strategy,
+ UmbrellaStrategy const& umbrella_strategy,
no_rescale_policy const& /*robust_policy*/)
: m_range_p(range_p)
, m_range_q(range_q)
, m_side_calc(range_p, range_q,
- intersection_strategy.get_side_strategy())
+ umbrella_strategy.get_side_strategy())
{}
inline point1_type const& rpi() const { return m_side_calc.get_pi(); }
@@ -354,15 +354,15 @@ template
<
typename UniqueSubRange1, typename UniqueSubRange2,
typename TurnPoint,
- typename IntersectionStrategy,
+ typename UmbrellaStrategy,
typename RobustPolicy
>
class intersection_info
: public intersection_info_base<UniqueSubRange1, UniqueSubRange2,
- TurnPoint, IntersectionStrategy, RobustPolicy>
+ TurnPoint, UmbrellaStrategy, RobustPolicy>
{
typedef intersection_info_base<UniqueSubRange1, UniqueSubRange2,
- TurnPoint, IntersectionStrategy, RobustPolicy> base;
+ TurnPoint, UmbrellaStrategy, RobustPolicy> base;
public:
typedef segment_intersection_points
@@ -387,8 +387,9 @@ public:
policies::relate::segments_direction
> intersection_policy_type;
- typedef IntersectionStrategy intersection_strategy_type;
- typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
+ typedef UmbrellaStrategy intersection_strategy_type;
+ typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type;
+ typedef typename UmbrellaStrategy::cs_tag cs_tag;
typedef model::referring_segment<point1_type const> segment_type1;
typedef model::referring_segment<point2_type const> segment_type2;
@@ -400,18 +401,18 @@ public:
intersection_info(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
- IntersectionStrategy const& intersection_strategy,
+ UmbrellaStrategy const& umbrella_strategy,
RobustPolicy const& robust_policy)
: base(range_p, range_q,
- intersection_strategy, robust_policy)
- , m_result(intersection_strategy.apply(
+ umbrella_strategy, robust_policy)
+ , m_result(umbrella_strategy.apply(
segment_type1(range_p.at(0), range_p.at(1)),
segment_type2(range_q.at(0), range_q.at(1)),
intersection_policy_type(),
robust_policy,
base::rpi(), base::rpj(),
base::rqi(), base::rqj()))
- , m_intersection_strategy(intersection_strategy)
+ , m_intersection_strategy(umbrella_strategy)
, m_robust_policy(robust_policy)
{}
@@ -452,7 +453,7 @@ public:
{
// qk is collinear with both p1 and p2,
// verify if pk goes backwards w.r.t. pi/pj
- return direction_code(base::rpi(), base::rpj(), base::rpk()) == -1;
+ return direction_code<cs_tag>(base::rpi(), base::rpj(), base::rpk()) == -1;
}
// qk is at opposite side of p1/p2, therefore
@@ -488,7 +489,7 @@ public:
{
if (pk_q1 == 0)
{
- return direction_code(base::rqi(), base::rqj(), base::rqk()) == -1;
+ return direction_code<cs_tag>(base::rqi(), base::rqj(), base::rqk()) == -1;
}
return true;
@@ -523,7 +524,7 @@ private:
}
result_type m_result;
- IntersectionStrategy const& m_intersection_strategy;
+ UmbrellaStrategy 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 f8272794bd..5b5273392c 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
@@ -44,7 +44,7 @@ struct get_turn_info_linear_areal
typename UniqueSubRange1,
typename UniqueSubRange2,
typename TurnInfo,
- typename IntersectionStrategy,
+ typename UmbrellaStrategy,
typename RobustPolicy,
typename OutputIterator
>
@@ -52,7 +52,7 @@ struct get_turn_info_linear_areal
UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
TurnInfo const& tp_model,
- IntersectionStrategy const& strategy,
+ UmbrellaStrategy const& umbrella_strategy,
RobustPolicy const& robust_policy,
OutputIterator out)
{
@@ -60,11 +60,11 @@ struct get_turn_info_linear_areal
<
UniqueSubRange1, UniqueSubRange2,
typename TurnInfo::point_type,
- IntersectionStrategy,
+ UmbrellaStrategy,
RobustPolicy
> inters_info;
- inters_info inters(range_p, range_q, strategy, robust_policy);
+ inters_info inters(range_p, range_q, umbrella_strategy, robust_policy);
char const method = inters.d_info().how;
@@ -79,7 +79,7 @@ struct get_turn_info_linear_areal
case 's' : // starts from the middle
get_turn_info_for_endpoint<true, true>(range_p, range_q,
tp_model, inters, method_none, out,
- strategy.get_point_in_point_strategy());
+ umbrella_strategy.get_point_in_point_strategy());
break;
case 'd' : // disjoint: never do anything
@@ -89,30 +89,27 @@ struct get_turn_info_linear_areal
{
if ( get_turn_info_for_endpoint<false, true>(range_p, range_q,
tp_model, inters, method_touch_interior, out,
- strategy.get_point_in_point_strategy()) )
+ umbrella_strategy.get_point_in_point_strategy()) )
{
// do nothing
}
else
{
- typedef touch_interior
- <
- TurnInfo
- > policy;
+ typedef touch_interior<TurnInfo> handler;
// If Q (1) arrives (1)
if ( inters.d_info().arrival[1] == 1 )
{
- policy::template apply<0>(range_p, range_q, tp,
+ handler::template apply<0>(range_p, range_q, tp,
inters.i_info(), inters.d_info(),
- inters.sides());
+ inters.sides(), umbrella_strategy);
}
else
{
// Swap p/q
- policy::template apply<1>(range_q, range_p,
+ handler::template apply<1>(range_q, range_p,
tp, inters.i_info(), inters.d_info(),
- inters.get_swapped_sides());
+ inters.get_swapped_sides(), umbrella_strategy);
}
if ( tp.operations[1].operation == operation_blocked )
@@ -127,7 +124,7 @@ struct get_turn_info_linear_areal
// this function assumes that 'u' must be set for a spike
calculate_spike_operation(tp.operations[0].operation,
inters,
- strategy.get_point_in_point_strategy());
+ umbrella_strategy.get_point_in_point_strategy());
*out++ = tp;
}
@@ -147,14 +144,15 @@ struct get_turn_info_linear_areal
// Both touch (both arrive there)
if ( get_turn_info_for_endpoint<false, true>(range_p, range_q,
tp_model, inters, method_touch, out,
- strategy.get_point_in_point_strategy()) )
+ umbrella_strategy.get_point_in_point_strategy()) )
{
// do nothing
}
else
{
touch<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(), inters.sides());
+ inters.i_info(), inters.d_info(), inters.sides(),
+ umbrella_strategy);
if ( tp.operations[1].operation == operation_blocked )
{
@@ -220,7 +218,7 @@ struct get_turn_info_linear_areal
bool ignore_spike
= calculate_spike_operation(tp.operations[0].operation,
inters,
- strategy.get_point_in_point_strategy());
+ umbrella_strategy.get_point_in_point_strategy());
if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)
|| ignore_spike
@@ -236,7 +234,7 @@ struct get_turn_info_linear_areal
{
if ( get_turn_info_for_endpoint<true, true>(range_p, range_q,
tp_model, inters, method_equal, out,
- strategy.get_point_in_point_strategy()) )
+ umbrella_strategy.get_point_in_point_strategy()) )
{
// do nothing
}
@@ -249,7 +247,8 @@ struct get_turn_info_linear_areal
// Both equal
// or collinear-and-ending at intersection point
equal<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(), inters.sides());
+ inters.i_info(), inters.d_info(), inters.sides(),
+ umbrella_strategy);
turn_transformer_ec<false> transformer(method_touch);
transformer(tp);
@@ -280,7 +279,7 @@ struct get_turn_info_linear_areal
if ( get_turn_info_for_endpoint<true, true>(
range_p, range_q,
tp_model, inters, method_collinear, out,
- strategy.get_point_in_point_strategy()) )
+ umbrella_strategy.get_point_in_point_strategy()) )
{
// do nothing
}
@@ -297,7 +296,8 @@ struct get_turn_info_linear_areal
{
// Collinear, but similar thus handled as equal
equal<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(), inters.sides());
+ inters.i_info(), inters.d_info(), inters.sides(),
+ umbrella_strategy);
method_replace = method_touch;
version = append_equal;
@@ -359,13 +359,13 @@ struct get_turn_info_linear_areal
if ( range_p.is_first_segment()
&& equals::equals_point_point(range_p.at(0), tp.point,
- strategy.get_point_in_point_strategy()) )
+ umbrella_strategy.get_point_in_point_strategy()) )
{
tp.operations[0].position = position_front;
}
else if ( range_p.is_last_segment()
&& equals::equals_point_point(range_p.at(1), tp.point,
- strategy.get_point_in_point_strategy()) )
+ umbrella_strategy.get_point_in_point_strategy()) )
{
tp.operations[0].position = position_back;
}
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 217f4a340b..0ea937a1e4 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
@@ -39,7 +39,7 @@ struct get_turn_info_linear_linear
typename UniqueSubRange1,
typename UniqueSubRange2,
typename TurnInfo,
- typename IntersectionStrategy,
+ typename UmbrellaStrategy,
typename RobustPolicy,
typename OutputIterator
>
@@ -47,7 +47,7 @@ struct get_turn_info_linear_linear
UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
TurnInfo const& tp_model,
- IntersectionStrategy const& strategy,
+ UmbrellaStrategy const& umbrella_strategy,
RobustPolicy const& robust_policy,
OutputIterator out)
{
@@ -55,11 +55,11 @@ struct get_turn_info_linear_linear
<
UniqueSubRange1, UniqueSubRange2,
typename TurnInfo::point_type,
- IntersectionStrategy,
+ UmbrellaStrategy,
RobustPolicy
> inters_info;
- inters_info inters(range_p, range_q, strategy, robust_policy);
+ inters_info inters(range_p, range_q, umbrella_strategy, robust_policy);
char const method = inters.d_info().how;
@@ -75,7 +75,7 @@ struct get_turn_info_linear_linear
get_turn_info_for_endpoint<true, true>
::apply(range_p, range_q,
tp_model, inters, method_none, out,
- strategy.get_point_in_point_strategy());
+ umbrella_strategy.get_point_in_point_strategy());
break;
case 'd' : // disjoint: never do anything
@@ -86,7 +86,7 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<false, true>
::apply(range_p, range_q,
tp_model, inters, method_touch_interior, out,
- strategy.get_point_in_point_strategy()) )
+ umbrella_strategy.get_point_in_point_strategy()) )
{
// do nothing
}
@@ -102,14 +102,16 @@ struct get_turn_info_linear_linear
{
policy::template apply<0>(range_p, range_q, tp,
inters.i_info(), inters.d_info(),
- inters.sides());
+ inters.sides(),
+ umbrella_strategy);
}
else
{
// Swap p/q
policy::template apply<1>(range_q, range_p, tp,
inters.i_info(), inters.d_info(),
- inters.get_swapped_sides());
+ inters.get_swapped_sides(),
+ umbrella_strategy);
}
if ( tp.operations[0].operation == operation_blocked )
@@ -144,14 +146,16 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<false, true>
::apply(range_p, range_q,
tp_model, inters, method_touch, out,
- strategy.get_point_in_point_strategy()) )
+ umbrella_strategy.get_point_in_point_strategy()) )
{
// do nothing
}
else
{
touch<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(), inters.sides());
+ inters.i_info(), inters.d_info(),
+ inters.sides(),
+ umbrella_strategy);
// workarounds for touch<> not taking spikes into account starts here
// those was discovered empirically
@@ -274,7 +278,7 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<true, true>
::apply(range_p, range_q,
tp_model, inters, method_equal, out,
- strategy.get_point_in_point_strategy()) )
+ umbrella_strategy.get_point_in_point_strategy()) )
{
// do nothing
}
@@ -288,7 +292,8 @@ struct get_turn_info_linear_linear
// Both equal
// or collinear-and-ending at intersection point
equal<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(), inters.sides());
+ inters.i_info(), inters.d_info(), inters.sides(),
+ umbrella_strategy);
operation_type spike_op
= ( tp.operations[0].operation != operation_continue
@@ -328,7 +333,7 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<true, true>
::apply(range_p, range_q,
tp_model, inters, method_collinear, out,
- strategy.get_point_in_point_strategy()) )
+ umbrella_strategy.get_point_in_point_strategy()) )
{
// do nothing
}
@@ -347,7 +352,8 @@ struct get_turn_info_linear_linear
{
// Collinear, but similar thus handled as equal
equal<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(), inters.sides());
+ inters.i_info(), inters.d_info(), inters.sides(),
+ umbrella_strategy);
method_replace = method_touch;
if ( tp.operations[0].operation != operation_continue
@@ -410,7 +416,7 @@ struct get_turn_info_linear_linear
// degenerate points
if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) )
{
- typedef typename IntersectionStrategy::point_in_point_strategy_type
+ typedef typename UmbrellaStrategy::point_in_point_strategy_type
equals_strategy_type;
only_convert::apply(tp, inters.i_info());
diff --git a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
index 6bb30fcce5..5ae246ec92 100644
--- a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
+++ b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
@@ -22,9 +22,11 @@
#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
@@ -82,6 +84,14 @@ struct turn_operation_index
signed_size_type op_index; // only 0,1
};
+struct is_discarded
+{
+ template <typename Turn>
+ inline bool operator()(Turn const& turn) const
+ {
+ return turn.discarded;
+ }
+};
template <typename Turns>
struct less_by_fraction_and_type
@@ -246,7 +256,7 @@ inline void handle_colocation_cluster(Turns& turns,
turn_type& turn = turns[toi.turn_index];
turn_operation_type const& op = turn.operations[toi.op_index];
- BOOST_ASSERT(ref_op.seg_id == op.seg_id);
+ BOOST_GEOMETRY_ASSERT(ref_op.seg_id == op.seg_id);
if (ref_op.fraction == op.fraction)
{
@@ -256,7 +266,7 @@ inline void handle_colocation_cluster(Turns& turns,
{
ref_id = add_turn_to_cluster(ref_turn, cluster_per_segment, cluster_id);
}
- BOOST_ASSERT(ref_id != -1);
+ BOOST_GEOMETRY_ASSERT(ref_id != -1);
// ref_turn (both operations) are already added to cluster,
// so also "op" is already added to cluster,
@@ -504,6 +514,100 @@ inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters)
}
}
+template <typename Geometry0, typename Geometry1>
+inline segment_identifier get_preceding_segment_id(segment_identifier const& id,
+ Geometry0 const& geometry0, Geometry1 const& geometry1)
+{
+ segment_identifier result = id;
+
+ if (result.segment_index == 0)
+ {
+ // Assign to segment_count before decrement
+ result.segment_index
+ = id.source_index == 0
+ ? segment_count_on_ring(geometry0, id)
+ : segment_count_on_ring(geometry1, id);
+ }
+
+ result.segment_index--;
+
+ return result;
+}
+
+// Turns marked with method <start> can be generated but are often duplicate,
+// unless (by floating point precision) the preceding touching turn is just missed.
+// This means that all <start> (nearly) colocated with preceding touching turn
+// can be deleted. This is done before colocation itself (because in colocated,
+// they are only discarded, and that can give issues in traversal)
+template <typename Turns, typename Geometry0, typename Geometry1>
+inline void erase_colocated_start_turns(Turns& turns,
+ Geometry0 const& geometry0, Geometry1 const& geometry1)
+{
+ typedef std::pair<segment_identifier, segment_identifier> seg_id_pair;
+ typedef std::map<seg_id_pair, std::size_t> map_type;
+
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename boost::range_iterator<Turns const>::type turn_it;
+ typedef map_type::const_iterator map_it;
+
+ // Collect starting turns into map
+ map_type preceding_segments;
+ std::size_t turn_index = 0;
+ for (turn_it it = boost::begin(turns); it != boost::end(turns); ++it, ++turn_index)
+ {
+ turn_type const& turn = *it;
+ if (turn.method == method_start)
+ {
+ // Insert identifiers for preceding segments of both operations.
+ // (For self turns geometry1 == geometry2)
+ seg_id_pair const pair(
+ get_preceding_segment_id(turn.operations[0].seg_id, geometry0, geometry1),
+ get_preceding_segment_id(turn.operations[1].seg_id, geometry0, geometry1));
+
+ // There should exist only one turn with such ids
+ BOOST_GEOMETRY_ASSERT(preceding_segments.find(pair) == preceding_segments.end());
+
+ preceding_segments[pair] = turn_index;
+ }
+ }
+
+ if (preceding_segments.empty())
+ {
+ return;
+ }
+
+ // Find touching turns on preceding segment id combinations
+ bool has_discarded = false;
+ for (turn_it it = boost::begin(turns); it != boost::end(turns); ++it)
+ {
+ turn_type const& turn = *it;
+ if (turn.method == method_touch)
+ {
+ seg_id_pair const pair(turn.operations[0].seg_id,
+ turn.operations[1].seg_id);
+
+ map_it mit = preceding_segments.find(pair);
+
+ if (mit != preceding_segments.end())
+ {
+ // The found touching turn precedes the found starting turn.
+ // (To be completely sure we could verify if turn.point is (nearly) equal)
+ // These turns are duplicate, discard the starting turn.
+ has_discarded = true;
+ turn_type& extra_turn = turns[mit->second];
+ extra_turn.discarded = true;
+ }
+ }
+ }
+
+ if (has_discarded)
+ {
+ turns.erase(std::remove_if(boost::begin(turns), boost::end(turns),
+ is_discarded()),
+ boost::end(turns));
+ }
+}
+
template
<
overlay_type OverlayType,
@@ -537,11 +641,7 @@ inline void set_colocation(Turns& turns, Clusters const& clusters)
for (set_iterator it = ids.begin(); it != ids.end(); ++it)
{
turn_type& turn = turns[*it];
-
- if (both_target)
- {
- turn.has_colocated_both = true;
- }
+ turn.has_colocated_both = true;
}
}
}
@@ -733,7 +833,7 @@ struct is_turn_index
return indexed.turn_index == m_index;
}
- std::size_t m_index;
+ signed_size_type m_index;
};
@@ -832,7 +932,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
continue;
}
- if (OverlayType != overlay_difference
+ if (BOOST_GEOMETRY_CONDITION(OverlayType != overlay_difference)
&& is_self_turn<OverlayType>(turn))
{
// Difference needs the self-turns, TODO: investigate
diff --git a/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp b/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp
index 5ec2a10cf0..7124675b57 100644
--- a/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp
@@ -3,6 +3,11 @@
// Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -25,18 +30,68 @@ namespace boost { namespace geometry
namespace detail { namespace overlay
{
+
+template
+<
+ typename Point, typename Geometry,
+ typename Tag2 = typename geometry::tag<Geometry>::type
+>
+struct check_within_strategy
+{
+ template <typename Strategy>
+ static inline typename Strategy::template point_in_geometry_strategy<Point, Geometry>::type
+ within(Strategy const& strategy)
+ {
+ return strategy.template get_point_in_geometry_strategy<Point, Geometry>();
+ }
+
+ template <typename Strategy>
+ static inline typename Strategy::template point_in_geometry_strategy<Point, Geometry>::type
+ covered_by(Strategy const& strategy)
+ {
+ return strategy.template get_point_in_geometry_strategy<Point, Geometry>();
+ }
+};
+
+template <typename Point, typename Geometry>
+struct check_within_strategy<Point, Geometry, box_tag>
+{
+ template <typename Strategy>
+ static inline typename Strategy::within_point_box_strategy_type
+ within(Strategy const& )
+ {
+ return typename Strategy::within_point_box_strategy_type();
+ }
+
+ template <typename Strategy>
+ static inline typename Strategy::covered_by_point_box_strategy_type
+ covered_by(Strategy const&)
+ {
+ return typename Strategy::covered_by_point_box_strategy_type();
+ }
+};
+
+
template <overlay_type OverlayType>
struct check_within
{
- template <typename Turn, typename Geometry0, typename Geometry1>
+ template
+ <
+ typename Turn, typename Geometry0, typename Geometry1,
+ typename UmbrellaStrategy
+ >
static inline
bool apply(Turn const& turn, Geometry0 const& geometry0,
- Geometry1 const& geometry1)
+ Geometry1 const& geometry1, UmbrellaStrategy const& strategy)
{
+ typedef typename Turn::point_type point_type;
+
// Operations 0 and 1 have the same source index in self-turns
return turn.operations[0].seg_id.source_index == 0
- ? geometry::within(turn.point, geometry1)
- : geometry::within(turn.point, geometry0);
+ ? geometry::within(turn.point, geometry1,
+ check_within_strategy<point_type, Geometry1>::within(strategy))
+ : geometry::within(turn.point, geometry0,
+ check_within_strategy<point_type, Geometry0>::within(strategy));
}
};
@@ -44,24 +99,39 @@ struct check_within
template <>
struct check_within<overlay_difference>
{
- template <typename Turn, typename Geometry0, typename Geometry1>
+ template
+ <
+ typename Turn, typename Geometry0, typename Geometry1,
+ typename UmbrellaStrategy
+ >
static inline
bool apply(Turn const& turn, Geometry0 const& geometry0,
- Geometry1 const& geometry1)
+ Geometry1 const& geometry1, UmbrellaStrategy const& strategy)
{
+ typedef typename Turn::point_type point_type;
+
// difference = intersection(a, reverse(b))
// therefore we should reverse the meaning of within for geometry1
return turn.operations[0].seg_id.source_index == 0
- ? ! geometry::covered_by(turn.point, geometry1)
- : geometry::within(turn.point, geometry0);
+ ? ! geometry::covered_by(turn.point, geometry1,
+ check_within_strategy<point_type, Geometry1>::covered_by(strategy))
+ : geometry::within(turn.point, geometry0,
+ check_within_strategy<point_type, Geometry0>::within(strategy));
}
};
struct discard_turns
{
- template <typename Turns, typename Clusters, typename Geometry0, typename Geometry1>
+ template
+ <
+ typename Turns, typename Clusters,
+ typename Geometry0, typename Geometry1,
+ typename Strategy
+ >
static inline
- void apply(Turns& , Clusters const& , Geometry0 const& , Geometry1 const& )
+ void apply(Turns& , Clusters const& ,
+ Geometry0 const& , Geometry1 const& ,
+ Strategy const& )
{}
};
@@ -72,11 +142,17 @@ struct discard_closed_turns : discard_turns {};
template <>
struct discard_closed_turns<overlay_union, operation_union>
{
-
- template <typename Turns, typename Clusters, typename Geometry0, typename Geometry1>
+ // Point in Geometry Strategy
+ template
+ <
+ typename Turns, typename Clusters,
+ typename Geometry0, typename Geometry1,
+ typename Strategy
+ >
static inline
void apply(Turns& turns, Clusters const& /*clusters*/,
- Geometry0 const& geometry0, Geometry1 const& geometry1)
+ Geometry0 const& geometry0, Geometry1 const& geometry1,
+ Strategy const& strategy)
{
typedef typename boost::range_value<Turns>::type turn_type;
@@ -89,8 +165,8 @@ struct discard_closed_turns<overlay_union, operation_union>
if (! turn.discarded
&& is_self_turn<overlay_union>(turn)
- && check_within<overlay_union>::apply(turn,
- geometry0, geometry1))
+ && check_within<overlay_union>::apply(turn, geometry0,
+ geometry1, strategy))
{
// Turn is in the interior of other geometry
turn.discarded = true;
@@ -130,10 +206,11 @@ private :
}
template <typename Turns, typename Clusters,
- typename Geometry0, typename Geometry1>
+ typename Geometry0, typename Geometry1, typename Strategy>
static inline
void discard_clusters(Turns& turns, Clusters const& clusters,
- Geometry0 const& geometry0, Geometry1 const& geometry1)
+ Geometry0 const& geometry0, Geometry1 const& geometry1,
+ Strategy const& strategy)
{
for (typename Clusters::const_iterator cit = clusters.begin();
cit != clusters.end(); ++cit)
@@ -148,7 +225,8 @@ private :
cluster_info const& cinfo = cit->second;
signed_size_type const index = *cinfo.turn_indices.begin();
if (! check_within<OverlayType>::apply(turns[index],
- geometry0, geometry1))
+ geometry0, geometry1,
+ strategy))
{
// Discard all turns in cluster
for (std::set<signed_size_type>::const_iterator sit
@@ -165,12 +243,13 @@ private :
public :
template <typename Turns, typename Clusters,
- typename Geometry0, typename Geometry1>
+ typename Geometry0, typename Geometry1, typename Strategy>
static inline
void apply(Turns& turns, Clusters const& clusters,
- Geometry0 const& geometry0, Geometry1 const& geometry1)
+ Geometry0 const& geometry0, Geometry1 const& geometry1,
+ Strategy const& strategy)
{
- discard_clusters(turns, clusters, geometry0, geometry1);
+ discard_clusters(turns, clusters, geometry0, geometry1, strategy);
typedef typename boost::range_value<Turns>::type turn_type;
@@ -185,7 +264,8 @@ public :
// Check if it is within the other geometry
if (! turn.discarded
&& is_self_turn<overlay_intersection>(turn)
- && ! check_within<OverlayType>::apply(turn, geometry0, geometry1))
+ && ! check_within<OverlayType>::apply(turn, geometry0,
+ geometry1, strategy))
{
// It is not within another geometry, set it as non startable.
// It still might be traveled (#case_recursive_boxes_70)
diff --git a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
index 60255cd953..5e55d9db20 100644
--- a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
+++ b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015, 2017.
-// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2015, 2017, 2019.
+// Modifications copyright (c) 2014-2019 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
@@ -1290,11 +1290,13 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1,
typedef typename geometry::rescale_policy_type
<
- typename geometry::point_type<Geometry1>::type // TODO from both
+ typename geometry::point_type<Geometry1>::type, // TODO from both
+ typename Strategy::cs_tag
>::type rescale_policy_type;
rescale_policy_type robust_policy
- = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
+ = geometry::get_rescale_policy<rescale_policy_type>(
+ geometry1, geometry2, strategy);
return detail::intersection::insert
<
diff --git a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
index f0a7d6a7a8..a6e66b03d4 100644
--- a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2017, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, Oracle and/or its affiliates.
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -169,8 +169,7 @@ protected:
LinearGeometry1,
LinearGeometry2,
assign_policy
- >,
- RobustPolicy
+ >
>::apply(turns, linear1, linear2, interrupt_policy, strategy, robust_policy);
}
@@ -237,13 +236,12 @@ public:
Linear1,
Linear2,
detail::get_turns::get_turn_info_type
- <
- Linear1,
- Linear2,
- assign_policy
- >,
- RobustPolicy
- >::turn_info turn_info;
+ <
+ Linear1,
+ Linear2,
+ assign_policy
+ >
+ >::template turn_info_type<Strategy, RobustPolicy>::type turn_info;
typedef std::vector<turn_info> turns_container;
diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp
index 8a8561c136..e52d3741af 100644
--- a/boost/geometry/algorithms/detail/overlay/overlay.hpp
+++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland
-// This file was modified by Oracle on 2015, 2017.
-// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017, 2019.
+// Modifications copyright (c) 2015-2019, 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
@@ -334,14 +334,12 @@ std::cout << "get turns" << std::endl;
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "enrich" << std::endl;
#endif
- typename Strategy::side_strategy_type side_strategy = strategy.get_side_strategy();
+
cluster_type clusters;
std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
- geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns,
- clusters, geometry1, geometry2,
- robust_policy,
- side_strategy);
+ geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(
+ turns, clusters, geometry1, geometry2, robust_policy, strategy);
visitor.visit_turns(2, turns);
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
index 6f8fdd32b8..ca1e0adf52 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
@@ -2,7 +2,7 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// Copyright (c) 2015-2017, Oracle and/or its affiliates.
+// Copyright (c) 2015-2019, 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
@@ -128,12 +128,13 @@ class multipoint_linear_point
{
private:
// structs for partition -- start
+ template <typename ExpandPointStrategy>
struct expand_box_point
{
template <typename Box, typename Point>
static inline void apply(Box& total, Point const& point)
{
- geometry::expand(total, point);
+ geometry::expand(total, point, ExpandPointStrategy());
}
};
@@ -148,18 +149,20 @@ private:
inline void apply(Box& total, Segment const& segment) const
{
geometry::expand(total,
- geometry::return_envelope<Box>(segment, m_strategy));
+ geometry::return_envelope<Box>(segment, m_strategy),
+ m_strategy.get_box_expand_strategy());
}
EnvelopeStrategy const& m_strategy;
};
+ template <typename DisjointPointBoxStrategy>
struct overlaps_box_point
{
template <typename Box, typename Point>
static inline bool apply(Box const& box, Point const& point)
{
- return ! geometry::disjoint(point, box);
+ return ! geometry::disjoint(point, box, DisjointPointBoxStrategy());
}
};
@@ -239,6 +242,8 @@ private:
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
+ typedef typename Strategy::disjoint_point_box_strategy_type disjoint_point_box_strategy_type;
+ typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type;
// TODO: disjoint Segment/Box may be called in partition multiple times
// possibly for non-cartesian segments which could be slow. We should consider
@@ -252,8 +257,8 @@ private:
typename boost::range_value<MultiPoint>::type
>
>::apply(multipoint, segment_range(linear), item_visitor,
- expand_box_point(),
- overlaps_box_point(),
+ expand_box_point<expand_point_strategy_type>(),
+ overlaps_box_point<disjoint_point_box_strategy_type>(),
expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
index afe8f680be..22ed82bfe3 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2018, Oracle and/or its affiliates.
+// Copyright (c) 2014-2019, 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
@@ -257,6 +257,8 @@ struct multipoint_multipoint_point
OutputIterator oit,
Strategy const& strategy)
{
+ typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
+
if ( OverlayType != overlay_difference
&& boost::size(multipoint1) > boost::size(multipoint2) )
{
@@ -271,7 +273,7 @@ struct multipoint_multipoint_point
std::vector<point2_type> points2(boost::begin(multipoint2),
boost::end(multipoint2));
- geometry::less<> const less = geometry::less<>();
+ less_type const less = less_type();
std::sort(points2.begin(), points2.end(), less);
for (typename boost::range_iterator<MultiPoint1 const>::type
diff --git a/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
index 74f438775c..ecbcc9c230 100644
--- a/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
+++ b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2015 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.
+// This file was modified by Oracle on 2017, 2019.
+// Modifications copyright (c) 2017, 2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -19,12 +19,13 @@
#include <map>
#include <vector>
-#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/direction_code.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+#include <boost/geometry/util/condition.hpp>
+
namespace boost { namespace geometry
{
@@ -133,6 +134,8 @@ struct less_by_side
template <typename T>
inline bool operator()(const T& first, const T& second) const
{
+ typedef typename SideStrategy::cs_tag cs_tag;
+
LessOnSame on_same;
Compare compare;
@@ -144,8 +147,8 @@ struct less_by_side
// Both collinear. They might point into different directions: <------*------>
// If so, order the one going backwards as the very first.
- int const first_code = direction_code(m_p1, m_p2, first.point);
- int const second_code = direction_code(m_p1, m_p2, second.point);
+ int const first_code = direction_code<cs_tag>(m_p1, m_p2, first.point);
+ int const second_code = direction_code<cs_tag>(m_p1, m_p2, second.point);
// Order by code, backwards first, then forward.
return first_code != second_code
@@ -154,14 +157,14 @@ struct less_by_side
;
}
else if (side_first == 0
- && direction_code(m_p1, m_p2, first.point) == -1)
+ && direction_code<cs_tag>(m_p1, m_p2, first.point) == -1)
{
// First collinear and going backwards.
// Order as the very first, so return always true
return true;
}
else if (side_second == 0
- && direction_code(m_p1, m_p2, second.point) == -1)
+ && direction_code<cs_tag>(m_p1, m_p2, second.point) == -1)
{
// Second is collinear and going backwards
// Order as very last, so return always false
@@ -301,17 +304,17 @@ public :
{
if (op.seg_id.segment_index >= departure_seg_id.segment_index)
{
+ // dep.seg_id=5, op.seg_id=7, distance=2, being segments 5,6
return op.seg_id.segment_index - departure_seg_id.segment_index;
}
// Take wrap into account
- // Suppose ring_count=10 (10 points, 9 segments), dep.seg_id=7, op.seg_id=2, then distance=10-9+2
- // Generic function (is this used somewhere else too?)
- ring_identifier const rid(op.seg_id.source_index, op.seg_id.multi_index, op.seg_id.ring_index);
- signed_size_type const segment_count
- (op.seg_id.source_index == 0
- ? geometry::num_points(detail::overlay::get_ring<typename geometry::tag<Geometry1>::type>::apply(rid, geometry1))
- : geometry::num_points(detail::overlay::get_ring<typename geometry::tag<Geometry2>::type>::apply(rid, geometry2)));
- return ((segment_count - 1) - departure_seg_id.segment_index) + op.seg_id.segment_index;
+ // Suppose point_count=10 (10 points, 9 segments), dep.seg_id=7, op.seg_id=2,
+ // then distance=9-7+2=4, being segments 7,8,0,1
+ std::size_t const segment_count
+ = op.seg_id.source_index == 0
+ ? segment_count_on_ring(geometry1, op.seg_id)
+ : segment_count_on_ring(geometry2, op.seg_id);
+ return segment_count - departure_seg_id.segment_index + op.seg_id.segment_index;
}
void apply(Point const& turn_point)
@@ -369,7 +372,7 @@ public :
void find_open()
{
- if (OverlayType == overlay_buffer)
+ if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_buffer))
{
// For buffers, use piece index
std::map<signed_size_type, bool> handled;
diff --git a/boost/geometry/algorithms/detail/overlay/traversal.hpp b/boost/geometry/algorithms/detail/overlay/traversal.hpp
index 3a7d82ce0a..9eb94636a7 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal.hpp
@@ -282,7 +282,7 @@ public :
{
// For uu/ii, only switch sources if indicated
- if (OverlayType == overlay_buffer)
+ if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_buffer))
{
// Buffer does not use source_index (always 0).
return select_source_generic<&segment_identifier::multi_index>(
@@ -391,7 +391,8 @@ public :
return true;
}
- if (OverlayType == overlay_buffer && possible[0] && possible[1])
+ if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_buffer)
+ && possible[0] && possible[1])
{
// Buffers sometimes have multiple overlapping pieces, where remaining
// distance could lead to the wrong choice. Take the matching operation.
@@ -565,7 +566,7 @@ public :
result = select_cc_operation(turn, start_turn_index,
selected_op_index);
}
- else if (OverlayType == overlay_dissolve)
+ else if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_dissolve))
{
result = select_preferred_operation(turn, turn_index,
start_turn_index, selected_op_index);
@@ -636,7 +637,7 @@ public :
return 0;
}
- if (OverlayType != overlay_dissolve
+ if (BOOST_GEOMETRY_CONDITION(OverlayType != overlay_dissolve)
&& (op.enriched.count_left != 0 || op.enriched.count_right == 0))
{
// Check counts: in some cases interior rings might be generated with
@@ -803,8 +804,7 @@ public :
{
continue;
}
- if (is_self_turn<OverlayType>(cluster_turn)
- || cluster_turn.both(target_operation))
+ if (cluster_turn.both(target_operation))
{
// Not (yet) supported, can be cluster of u/u turns
return false;
@@ -898,7 +898,8 @@ public :
// Points to different target
return false;
}
- if (OverlayType == overlay_buffer && target.turn_index > 0)
+ if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_buffer)
+ && target.turn_index > 0)
{
// Target already assigned, so there are more targets
// or more ways to the same target
@@ -1029,7 +1030,8 @@ public :
turn_operation_type const& start_op,
int start_op_index) const
{
- if (OverlayType != overlay_buffer && OverlayType != overlay_dissolve)
+ if (BOOST_GEOMETRY_CONDITION(OverlayType != overlay_buffer
+ && OverlayType != overlay_dissolve))
{
return;
}
@@ -1128,22 +1130,25 @@ public :
int previous_op_index,
signed_size_type previous_turn_index,
segment_identifier const& previous_seg_id,
- bool is_start)
+ bool is_start, bool has_points)
{
turn_type const& current_turn = m_turns[turn_index];
if (BOOST_GEOMETRY_CONDITION(target_operation == operation_intersection))
{
- bool const back_at_start_cluster
- = current_turn.is_clustered()
- && m_turns[start_turn_index].cluster_id == current_turn.cluster_id;
-
- if (turn_index == start_turn_index || back_at_start_cluster)
+ if (has_points)
{
- // Intersection can always be finished if returning
- turn_index = start_turn_index;
- op_index = start_op_index;
- return true;
+ bool const back_at_start_cluster
+ = current_turn.is_clustered()
+ && m_turns[start_turn_index].cluster_id == current_turn.cluster_id;
+
+ if (turn_index == start_turn_index || back_at_start_cluster)
+ {
+ // Intersection can always be finished if returning
+ turn_index = start_turn_index;
+ op_index = start_op_index;
+ return true;
+ }
}
if (! current_turn.is_clustered()
diff --git a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
index 99b2834f15..2b182b872e 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
@@ -142,7 +142,7 @@ struct traversal_ring_creator
if (! m_trav.select_turn(start_turn_index, start_op_index,
turn_index, op_index,
previous_op_index, previous_turn_index, previous_seg_id,
- is_start))
+ is_start, current_ring.size() > 1))
{
return is_start
? traverse_error_no_next_ip_at_start
diff --git a/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
index 545b5e902c..e976bdb039 100644
--- a/boost/geometry/algorithms/detail/overlay/turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
@@ -33,6 +33,7 @@ enum method_type
method_touch_interior,
method_collinear,
method_equal,
+ method_start,
method_error
};
@@ -92,7 +93,6 @@ struct turn_info
bool touch_only; // True in case of method touch(interior) and lines do not cross
signed_size_type cluster_id; // For multiple turns on same location, > 0. Else -1. 0 is unused.
bool discarded;
-
bool has_colocated_both; // Colocated with a uu turn (for union) or ii (other)
Container operations;
diff --git a/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp b/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp
index 35ede0a0bb..502a5b0bb0 100644
--- a/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp
+++ b/boost/geometry/algorithms/detail/point_is_spike_or_equal.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, 2017.
-// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017, 2019.
+// Modifications copyright (c) 2015-2019 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
@@ -75,6 +75,8 @@ inline bool point_is_spike_or_equal(Point1 const& last_point, // prev | back
Point3 const& segment_b, // curr | back - 1 | spike's vertex
SideStrategy const& strategy)
{
+ typedef typename SideStrategy::cs_tag cs_tag;
+
int const side = strategy.apply(segment_a, segment_b, last_point);
if (side == 0)
{
@@ -86,7 +88,7 @@ inline bool point_is_spike_or_equal(Point1 const& last_point, // prev | back
std::cout << "spike detection failure with: " << r1 << " " << r2 << std::endl;
return r2;
#else
- return direction_code(segment_a, segment_b, last_point) < 1;
+ return direction_code<cs_tag>(segment_a, segment_b, last_point) < 1;
#endif
}
return false;
diff --git a/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
index fa0ab1ea0f..06192e38d6 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, 2017, 2018.
-// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019.
+// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -223,7 +223,10 @@ struct areal_areal
return;
// get and analyse turns
- typedef typename turns::get_turns<Geometry1, Geometry2>::turn_info turn_type;
+ typedef typename turns::get_turns
+ <
+ Geometry1, Geometry2
+ >::template turn_info_type<IntersectionStrategy>::type turn_type;
std::vector<turn_type> turns;
interrupt_policy_areal_areal<Result> interrupt_policy(geometry1, geometry2, result);
diff --git a/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
index dc927d9026..89101ff93c 100644
--- a/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
+++ b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
@@ -81,7 +81,7 @@ class boundary_checker<Geometry, WithinStrategy, multi_linestring_tag>
public:
typedef WithinStrategy equals_strategy_type;
-
+
boundary_checker(Geometry const& g)
: is_filled(false), geometry(g)
{}
@@ -91,6 +91,8 @@ public:
template <boundary_query BoundaryQuery>
bool is_endpoint_boundary(point_type const& pt) const
{
+ typedef geometry::less<point_type, -1, typename WithinStrategy::cs_tag> less_type;
+
typedef typename boost::range_size<Geometry>::type size_type;
size_type multi_count = boost::size(geometry);
@@ -142,7 +144,7 @@ public:
std::sort(boundary_points.begin(),
boundary_points.end(),
- geometry::less<point_type>());
+ less_type());
is_filled = true;
}
@@ -152,7 +154,7 @@ public:
std::equal_range(boundary_points.begin(),
boundary_points.end(),
pt,
- geometry::less<point_type>())
+ less_type())
);
return equal_points_count % 2 != 0;// && equal_points_count > 0; // the number is odd and > 0
diff --git a/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
index 81fc9e5b3b..018565f2ea 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, 2017, 2018.
-// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019.
+// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -219,21 +219,21 @@ struct linear_areal
>
{};
- template <typename Geom1, typename Geom2>
+ template <typename Geom1, typename Geom2, typename Strategy>
struct multi_turn_info
- : turns::get_turns<Geom1, Geom2>::turn_info
+ : turns::get_turns<Geom1, Geom2>::template turn_info_type<Strategy>::type
{
multi_turn_info() : priority(0) {}
int priority; // single-geometry sorting priority
};
- template <typename Geom1, typename Geom2>
+ template <typename Geom1, typename Geom2, typename Strategy>
struct turn_info_type
: boost::mpl::if_c
<
is_multi<Geometry2>::value,
- multi_turn_info<Geom1, Geom2>,
- typename turns::get_turns<Geom1, Geom2>::turn_info
+ multi_turn_info<Geom1, Geom2, Strategy>,
+ typename turns::get_turns<Geom1, Geom2>::template turn_info_type<Strategy>::type
>
{};
@@ -251,7 +251,7 @@ struct linear_areal
return;
// get and analyse turns
- typedef typename turn_info_type<Geometry1, Geometry2>::type turn_type;
+ typedef typename turn_info_type<Geometry1, Geometry2, IntersectionStrategy>::type turn_type;
std::vector<turn_type> turns;
interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result);
diff --git a/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
index 6c5d82fdea..7be6bc7880 100644
--- a/boost/geometry/algorithms/detail/relate/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
-// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019.
+// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -133,7 +133,10 @@ struct linear_linear
return;
// get and analyse turns
- typedef typename turns::get_turns<Geometry1, Geometry2>::turn_info turn_type;
+ typedef typename turns::get_turns
+ <
+ Geometry1, Geometry2
+ >::template turn_info_type<IntersectionStrategy>::type turn_type;
std::vector<turn_type> turns;
interrupt_policy_linear_linear<Result> interrupt_policy(result);
diff --git a/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp b/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp
index 8dec5ccdaf..7f9e138392 100644
--- a/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2017-2018 Oracle and/or its affiliates.
+// Copyright (c) 2017-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -113,7 +113,7 @@ template <typename Geometry, typename EqPPStrategy>
struct multi_point_geometry_eb<Geometry, EqPPStrategy, multi_linestring_tag>
{
// TODO: CS-specific less compare strategy derived from EqPPStrategy
- typedef geometry::less<> less_type;
+ typedef geometry::less<void, -1, typename EqPPStrategy::cs_tag> less_type;
template <typename Points>
struct boundary_visitor
@@ -257,21 +257,23 @@ struct multi_point_single_geometry
template <typename MultiPoint, typename MultiGeometry, bool Transpose>
class multi_point_multi_geometry_ii_ib
{
+ template <typename ExpandPointStrategy>
struct expand_box_point
{
template <typename Box, typename Point>
static inline void apply(Box& total, Point const& point)
{
- geometry::expand(total, point);
+ geometry::expand(total, point, ExpandPointStrategy());
}
};
+ template <typename ExpandBoxStrategy>
struct expand_box_box_pair
{
template <typename Box, typename BoxPair>
static inline void apply(Box& total, BoxPair const& box_pair)
{
- geometry::expand(total, box_pair.first);
+ geometry::expand(total, box_pair.first, ExpandBoxStrategy());
}
};
@@ -384,10 +386,18 @@ public:
{
item_visitor_type<Result, Strategy> visitor(multi_geometry, tc, result, strategy);
+ typedef expand_box_point
+ <
+ typename Strategy::expand_point_strategy_type
+ > expand_box_point_type;
typedef overlaps_box_point
<
typename Strategy::disjoint_point_box_strategy_type
> overlaps_box_point_type;
+ typedef expand_box_box_pair
+ <
+ typename Strategy::envelope_strategy_type::box_expand_strategy_type
+ > expand_box_box_pair_type;
typedef overlaps_box_box_pair
<
typename Strategy::disjoint_box_box_strategy_type
@@ -397,9 +407,9 @@ public:
<
box1_type
>::apply(multi_point, boxes, visitor,
- expand_box_point(),
+ expand_box_point_type(),
overlaps_box_point_type(),
- expand_box_box_pair(),
+ expand_box_box_pair_type(),
overlaps_box_box_pair_type());
}
@@ -431,7 +441,17 @@ struct multi_point_multi_geometry_ii_ib_ie
Result & result,
Strategy const& strategy)
{
- index::rtree<box_pair_type, index::rstar<4> > rt(boxes.begin(), boxes.end());
+ typedef strategy::index::services::from_strategy
+ <
+ Strategy
+ > index_strategy_from;
+ typedef index::parameters
+ <
+ index::rstar<4>, typename index_strategy_from::type
+ > index_parameters_type;
+ index::rtree<box_pair_type, index_parameters_type>
+ rtree(boxes.begin(), boxes.end(),
+ index_parameters_type(index::rstar<4>(), index_strategy_from::get(strategy)));
typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
@@ -446,7 +466,7 @@ struct multi_point_multi_geometry_ii_ib_ie
typename boost::range_value<MultiPoint>::type const& point = *it;
boxes_type boxes_found;
- rt.query(index::intersects(point), std::back_inserter(boxes_found));
+ rtree.query(index::intersects(point), std::back_inserter(boxes_found));
bool found_ii_or_ib = false;
for (boxes_iterator bi = boxes_found.begin() ; bi != boxes_found.end() ; ++bi)
diff --git a/boost/geometry/algorithms/detail/relate/point_point.hpp b/boost/geometry/algorithms/detail/relate/point_point.hpp
index d2a373f3c1..7103e2dc92 100644
--- a/boost/geometry/algorithms/detail/relate/point_point.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_point.hpp
@@ -148,6 +148,8 @@ struct multipoint_multipoint
Result & result,
Strategy const& /*strategy*/)
{
+ typedef typename Strategy::cs_tag cs_tag;
+
{
// TODO: throw on empty input?
bool empty1 = boost::empty(multi_point1);
@@ -171,17 +173,17 @@ struct multipoint_multipoint
// The geometry containing smaller number of points will be analysed first
if ( boost::size(multi_point1) < boost::size(multi_point2) )
{
- search_both<false>(multi_point1, multi_point2, result);
+ search_both<false, cs_tag>(multi_point1, multi_point2, result);
}
else
{
- search_both<true>(multi_point2, multi_point1, result);
+ search_both<true, cs_tag>(multi_point2, multi_point1, result);
}
relate::set<exterior, exterior, result_dimension<MultiPoint1>::value>(result);
}
- template <bool Transpose, typename MPt1, typename MPt2, typename Result>
+ template <bool Transpose, typename CSTag, typename MPt1, typename MPt2, typename Result>
static inline void search_both(MPt1 const& first_sorted_mpt, MPt2 const& first_iterated_mpt,
Result & result)
{
@@ -190,7 +192,7 @@ struct multipoint_multipoint
|| relate::may_update<exterior, interior, '0'>(result) )
{
// NlogN + MlogN
- bool is_disjoint = search<Transpose>(first_sorted_mpt, first_iterated_mpt, result);
+ bool is_disjoint = search<Transpose, CSTag>(first_sorted_mpt, first_iterated_mpt, result);
if ( BOOST_GEOMETRY_CONDITION(is_disjoint || result.interrupt) )
return;
@@ -201,11 +203,12 @@ struct multipoint_multipoint
|| relate::may_update<exterior, interior, '0'>(result) )
{
// MlogM + NlogM
- search<! Transpose>(first_iterated_mpt, first_sorted_mpt, result);
+ search<! Transpose, CSTag>(first_iterated_mpt, first_sorted_mpt, result);
}
}
template <bool Transpose,
+ typename CSTag,
typename SortedMultiPoint,
typename IteratedMultiPoint,
typename Result>
@@ -215,9 +218,11 @@ struct multipoint_multipoint
{
// sort points from the 1 MPt
typedef typename geometry::point_type<SortedMultiPoint>::type point_type;
+ typedef geometry::less<void, -1, CSTag> less_type;
+
std::vector<point_type> points(boost::begin(sorted_mpt), boost::end(sorted_mpt));
- geometry::less<> const less = geometry::less<>();
+ less_type const less = less_type();
std::sort(points.begin(), points.end(), less);
bool found_inside = false;
diff --git a/boost/geometry/algorithms/detail/relate/topology_check.hpp b/boost/geometry/algorithms/detail/relate/topology_check.hpp
index a12acaf42b..ab42504ec0 100644
--- a/boost/geometry/algorithms/detail/relate/topology_check.hpp
+++ b/boost/geometry/algorithms/detail/relate/topology_check.hpp
@@ -163,8 +163,7 @@ struct topology_check<MultiLinestring, EqPPStrategy, multi_linestring_tag>
}
private:
-// TODO: CS-specific less derived from EqPPStrategy
- typedef geometry::less<> less_type;
+ typedef geometry::less<void, -1, typename EqPPStrategy::cs_tag> less_type;
void init() const
{
diff --git a/boost/geometry/algorithms/detail/relate/turns.hpp b/boost/geometry/algorithms/detail/relate/turns.hpp
index 01c4304fa4..1ea6c4dba0 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, 2017.
-// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2019.
+// Modifications copyright (c) 2013-2019 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
@@ -47,18 +47,30 @@ template
typename GetTurnPolicy = detail::get_turns::get_turn_info_type
<
Geometry1, Geometry2, assign_policy<>
- >,
- typename RobustPolicy = typename geometry::rescale_overlay_policy_type
- <
- Geometry1,
- Geometry2
- >::type
+ >
>
struct get_turns
{
typedef typename geometry::point_type<Geometry1>::type point1_type;
- typedef overlay::turn_info
+ template <typename Strategy>
+ struct robust_policy_type
+ : geometry::rescale_overlay_policy_type
+ <
+ Geometry1,
+ Geometry2,
+ typename Strategy::cs_tag
+ >
+ {};
+
+ template
+ <
+ typename Strategy,
+ typename RobustPolicy = typename robust_policy_type<Strategy>::type
+ >
+ struct turn_info_type
+ {
+ typedef overlay::turn_info
<
point1_type,
typename segment_ratio_type<point1_type, RobustPolicy>::type,
@@ -70,7 +82,8 @@ struct get_turns
point1_type, RobustPolicy
>::type
>::type
- > turn_info;
+ > type;
+ };
template <typename Turns>
static inline void apply(Turns & turns,
@@ -94,15 +107,16 @@ struct get_turns
InterruptPolicy & interrupt_policy,
IntersectionStrategy const& intersection_strategy)
{
- RobustPolicy robust_policy = geometry::get_rescale_policy
- <
- RobustPolicy
- >(geometry1, geometry2);
+ typedef typename robust_policy_type<IntersectionStrategy>::type robust_policy_t;
+
+ robust_policy_t robust_policy
+ = geometry::get_rescale_policy<robust_policy_t>(
+ geometry1, geometry2, intersection_strategy);
apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy, robust_policy);
}
- template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy>
+ template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy, typename RobustPolicy>
static inline void apply(Turns & turns,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
diff --git a/boost/geometry/algorithms/detail/within/multi_point.hpp b/boost/geometry/algorithms/detail/within/multi_point.hpp
index 359853f6a4..273784a7bc 100644
--- a/boost/geometry/algorithms/detail/within/multi_point.hpp
+++ b/boost/geometry/algorithms/detail/within/multi_point.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2017 Oracle and/or its affiliates.
+// Copyright (c) 2017, 2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -73,8 +73,10 @@ struct multi_point_multi_point
Strategy const& /*strategy*/)
{
typedef typename boost::range_value<MultiPoint2>::type point2_type;
+ typedef typename Strategy::cs_tag cs_tag;
+ typedef geometry::less<void, -1, cs_tag> less_type;
- geometry::less<> const less = geometry::less<>();
+ less_type const less = less_type();
std::vector<point2_type> points2(boost::begin(multi_point2), boost::end(multi_point2));
std::sort(points2.begin(), points2.end(), less);
@@ -114,7 +116,7 @@ struct multi_point_single_geometry
LinearOrAreal const& linear_or_areal,
Strategy const& strategy)
{
- typedef typename boost::range_value<MultiPoint>::type point1_type;
+ //typedef typename boost::range_value<MultiPoint>::type point1_type;
typedef typename point_type<LinearOrAreal>::type point2_type;
typedef model::box<point2_type> box2_type;
@@ -123,10 +125,7 @@ struct multi_point_single_geometry
geometry::envelope(linear_or_areal, box, strategy.get_envelope_strategy());
geometry::detail::expand_by_epsilon(box);
- typedef typename strategy::covered_by::services::default_strategy
- <
- point1_type, box2_type
- >::type point_in_box_type;
+ typedef typename Strategy::disjoint_point_box_strategy_type point_in_box_type;
// Test each Point with envelope and then geometry if needed
// If in the exterior, break
@@ -196,7 +195,17 @@ struct multi_point_multi_geometry
}
// Create R-tree
- index::rtree<box_pair_type, index::rstar<4> > rtree(boxes.begin(), boxes.end());
+ typedef strategy::index::services::from_strategy
+ <
+ Strategy
+ > index_strategy_from;
+ typedef index::parameters
+ <
+ index::rstar<4>, typename index_strategy_from::type
+ > index_parameters_type;
+ index::rtree<box_pair_type, index_parameters_type>
+ rtree(boxes.begin(), boxes.end(),
+ index_parameters_type(index::rstar<4>(), index_strategy_from::get(strategy)));
// For each point find overlapping envelopes and test corresponding single geometries
// If a point is in the exterior break
@@ -214,15 +223,21 @@ struct multi_point_multi_geometry
bool found_boundary = false;
int boundaries = 0;
- typedef typename box_pair_vector::const_iterator iterator;
- for ( iterator box_it = inters_boxes.begin() ; box_it != inters_boxes.end() ; ++box_it )
+ typedef typename box_pair_vector::const_iterator box_iterator;
+ for (box_iterator box_it = inters_boxes.begin() ;
+ box_it != inters_boxes.end() ; ++box_it )
{
- int in_val = point_in_geometry(*it, range::at(linear_or_areal, box_it->second), strategy);
+ int const in_val = point_in_geometry(*it,
+ range::at(linear_or_areal, box_it->second), strategy);
if (in_val > 0)
+ {
found_interior = true;
+ }
else if (in_val == 0)
+ {
++boundaries;
+ }
// If the result was set previously (interior or
// interior/boundary found) the only thing that needs to be
@@ -234,12 +249,16 @@ struct multi_point_multi_geometry
}
}
- if ( boundaries > 0)
+ if (boundaries > 0)
{
if (is_linear && boundaries % 2 == 0)
+ {
found_interior = true;
+ }
else
+ {
found_boundary = true;
+ }
}
// exterior
diff --git a/boost/geometry/algorithms/difference.hpp b/boost/geometry/algorithms/difference.hpp
index c11ceca243..7a96e130dc 100644
--- a/boost/geometry/algorithms/difference.hpp
+++ b/boost/geometry/algorithms/difference.hpp
@@ -2,8 +2,8 @@
// 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.
+// This file was modified by Oracle on 2017, 2019.
+// Modifications copyright (c) 2017, 2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -55,13 +55,11 @@ template
typename GeometryOut,
typename Geometry1,
typename Geometry2,
- typename RobustPolicy,
typename OutputIterator,
typename Strategy
>
inline OutputIterator difference_insert(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- RobustPolicy const& robust_policy,
OutputIterator out,
Strategy const& strategy)
{
@@ -69,6 +67,17 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
concepts::check<Geometry2 const>();
concepts::check<GeometryOut>();
+ typedef typename geometry::rescale_overlay_policy_type
+ <
+ Geometry1,
+ Geometry2,
+ typename Strategy::cs_tag
+ >::type rescale_policy_type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(
+ geometry1, geometry2, strategy);
+
return geometry::dispatch::intersection_insert
<
Geometry1, Geometry2,
@@ -100,12 +109,10 @@ template
typename GeometryOut,
typename Geometry1,
typename Geometry2,
- typename RobustPolicy,
typename OutputIterator
>
inline OutputIterator difference_insert(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- RobustPolicy const& robust_policy,
OutputIterator out)
{
typedef typename strategy::relate::services::default_strategy
@@ -114,8 +121,8 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
Geometry2
>::type strategy_type;
- return difference_insert<GeometryOut>(geometry1, geometry2,
- robust_policy, out, strategy_type());
+ return difference_insert<GeometryOut>(geometry1, geometry2, out,
+ strategy_type());
}
@@ -131,20 +138,18 @@ struct difference
<
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,
+ geometry1, geometry2,
range::back_inserter(output_collection),
strategy);
}
@@ -153,19 +158,17 @@ struct difference
<
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,
+ geometry1, geometry2,
range::back_inserter(output_collection));
}
};
@@ -185,18 +188,7 @@ struct difference
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);
}
diff --git a/boost/geometry/algorithms/sym_difference.hpp b/boost/geometry/algorithms/sym_difference.hpp
index 725230cd5b..a281bf1db5 100644
--- a/boost/geometry/algorithms/sym_difference.hpp
+++ b/boost/geometry/algorithms/sym_difference.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015, 2017.
-// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017, 2019.
+// Modifications copyright (c) 2015-2019 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
@@ -234,13 +234,11 @@ template
typename GeometryOut,
typename Geometry1,
typename Geometry2,
- typename RobustPolicy,
typename OutputIterator,
typename Strategy
>
inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- RobustPolicy const& robust_policy,
OutputIterator out,
Strategy const& strategy)
{
@@ -248,6 +246,17 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
concepts::check<Geometry2 const>();
concepts::check<GeometryOut>();
+ typedef typename geometry::rescale_overlay_policy_type
+ <
+ Geometry1,
+ Geometry2,
+ typename Strategy::cs_tag
+ >::type rescale_policy_type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(
+ geometry1, geometry2, strategy);
+
return dispatch::sym_difference_insert
<
Geometry1, Geometry2, GeometryOut
@@ -274,12 +283,10 @@ template
typename GeometryOut,
typename Geometry1,
typename Geometry2,
- typename RobustPolicy,
typename OutputIterator
>
inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- RobustPolicy const& robust_policy, OutputIterator out)
+ Geometry2 const& geometry2, OutputIterator out)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -290,7 +297,7 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
typename cs_tag<GeometryOut>::type
>::type strategy_type;
- return sym_difference_insert<GeometryOut>(geometry1, geometry2, robust_policy, out, strategy_type());
+ return sym_difference_insert<GeometryOut>(geometry1, geometry2, out, strategy_type());
}
}} // namespace detail::sym_difference
@@ -305,20 +312,18 @@ struct sym_difference
<
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,
+ geometry1, geometry2,
range::back_inserter(output_collection),
strategy);
}
@@ -327,19 +332,17 @@ struct sym_difference
<
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,
+ geometry1, geometry2,
range::back_inserter(output_collection));
}
};
@@ -359,18 +362,7 @@ struct sym_difference
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);
}
diff --git a/boost/geometry/algorithms/union.hpp b/boost/geometry/algorithms/union.hpp
index d1d04d4045..de47795629 100644
--- a/boost/geometry/algorithms/union.hpp
+++ b/boost/geometry/algorithms/union.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2017, 2018.
-// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2017, 2018, 2019.
+// Modifications copyright (c) 2014-2019 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
@@ -211,19 +211,20 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
concepts::check<Geometry2 const>();
concepts::check<GeometryOut>();
+ typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<GeometryOut>::type
+ >::type strategy;
+
typedef typename geometry::rescale_overlay_policy_type
<
Geometry1,
Geometry2
>::type rescale_policy_type;
- typename strategy::intersection::services::default_strategy
- <
- typename cs_tag<GeometryOut>::type
- >::type strategy;
-
rescale_policy_type robust_policy
- = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
+ = geometry::get_rescale_policy<rescale_policy_type>(
+ geometry1, geometry2, strategy);
return dispatch::union_insert
<
@@ -244,18 +245,27 @@ struct union_
<
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;
+ typedef typename geometry::rescale_overlay_policy_type
+ <
+ Geometry1,
+ Geometry2,
+ typename Strategy::cs_tag
+ >::type rescale_policy_type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(
+ geometry1, geometry2, strategy);
+
dispatch::union_insert
<
Geometry1, Geometry2, geometry_out
@@ -268,29 +278,20 @@ struct union_
<
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::relate::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
- dispatch::union_insert
- <
- Geometry1, Geometry2, geometry_out
- >::apply(geometry1, geometry2, robust_policy,
- range::back_inserter(output_collection),
- strategy_type());
+ apply(geometry1, geometry2, output_collection, strategy_type());
}
};
@@ -313,18 +314,7 @@ struct union_
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);
}
diff --git a/boost/geometry/core/config.hpp b/boost/geometry/core/config.hpp
index c068e98cc7..852cda4792 100644
--- a/boost/geometry/core/config.hpp
+++ b/boost/geometry/core/config.hpp
@@ -1,5 +1,6 @@
// Boost.Geometry
+// Copyright (c) 2019 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -17,6 +18,10 @@
#define BOOST_GEOMETRY_CXX11_ARRAY_UNIFIED_INITIALIZATION
#endif
+// Defining this selects Kramer rule for segment-intersection
+// That is default behaviour.
+#define BOOST_GEOMETRY_USE_KRAMER_RULE
+
// Rescaling is turned on, unless NO_ROBUSTNESS is defined
// In future versions of Boost.Geometry, it will be turned off by default
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
diff --git a/boost/geometry/formulas/differential_quantities.hpp b/boost/geometry/formulas/differential_quantities.hpp
index 6d4c223286..789275f145 100644
--- a/boost/geometry/formulas/differential_quantities.hpp
+++ b/boost/geometry/formulas/differential_quantities.hpp
@@ -11,6 +11,7 @@
#ifndef BOOST_GEOMETRY_FORMULAS_INVERSE_DIFFERENTIAL_QUANTITIES_HPP
#define BOOST_GEOMETRY_FORMULAS_INVERSE_DIFFERENTIAL_QUANTITIES_HPP
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
@@ -73,6 +74,8 @@ public:
CT const sig_12 = dlon / one_minus_f;
if (BOOST_GEOMETRY_CONDITION(EnableReducedLength))
{
+ BOOST_GEOMETRY_ASSERT((-math::pi<CT>() <= azimuth && azimuth <= math::pi<CT>()));
+
int azi_sign = math::sign(azimuth) >= 0 ? 1 : -1; // for antipodal
CT m12 = azi_sign * sin(sig_12) * b;
reduced_length = m12;
diff --git a/boost/geometry/formulas/thomas_direct.hpp b/boost/geometry/formulas/thomas_direct.hpp
index 7b61616af6..2218ea9950 100644
--- a/boost/geometry/formulas/thomas_direct.hpp
+++ b/boost/geometry/formulas/thomas_direct.hpp
@@ -15,6 +15,7 @@
#include <boost/math/constants/constants.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/util/condition.hpp>
@@ -80,6 +81,8 @@ public:
CT const pi = math::pi<CT>();
CT const pi_half = pi / c2;
+ BOOST_GEOMETRY_ASSERT(-pi <= azimuth12 && azimuth12 <= pi);
+
// keep azimuth small - experiments show low accuracy
// if the azimuth is closer to (+-)180 deg.
CT azi12_alt = azimuth12;
diff --git a/boost/geometry/index/detail/algorithms/bounds.hpp b/boost/geometry/index/detail/algorithms/bounds.hpp
index a62fda070c..2a0fa9ced6 100644
--- a/boost/geometry/index/detail/algorithms/bounds.hpp
+++ b/boost/geometry/index/detail/algorithms/bounds.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -13,9 +17,11 @@
#include <boost/geometry/index/detail/bounded_view.hpp>
-namespace boost { namespace geometry { namespace index { namespace detail {
+namespace boost { namespace geometry { namespace index { namespace detail
+{
-namespace dispatch {
+namespace dispatch
+{
template <typename Geometry,
typename Bounds,
@@ -23,7 +29,8 @@ template <typename Geometry,
typename TagBounds = typename geometry::tag<Bounds>::type>
struct bounds
{
- static inline void apply(Geometry const& g, Bounds & b)
+ template <typename Strategy>
+ static inline void apply(Geometry const& g, Bounds & b, Strategy const& )
{
geometry::convert(g, b);
}
@@ -32,59 +39,184 @@ struct bounds
template <typename Geometry, typename Bounds>
struct bounds<Geometry, Bounds, segment_tag, box_tag>
{
- static inline void apply(Geometry const& g, Bounds & b)
+ template <typename Strategy>
+ static inline void apply(Geometry const& g, Bounds & b, Strategy const& s)
{
- index::detail::bounded_view<Geometry, Bounds> v(g);
+ index::detail::bounded_view<Geometry, Bounds, Strategy> v(g, s);
geometry::convert(v, b);
}
};
+
} // namespace dispatch
-template <typename Geometry, typename Bounds>
-inline void bounds(Geometry const& g, Bounds & b)
+
+template <typename Geometry, typename Bounds, typename Strategy>
+inline void bounds(Geometry const& g, Bounds & b, Strategy const& s)
{
concepts::check_concepts_and_equal_dimensions<Geometry const, Bounds>();
- dispatch::bounds<Geometry, Bounds>::apply(g, b);
+ dispatch::bounds<Geometry, Bounds>::apply(g, b, s);
}
-namespace dispatch {
-template <typename Geometry,
+namespace dispatch
+{
+
+template <typename Bounds,
+ typename Geometry,
+ typename TagBounds = typename geometry::tag<Bounds>::type,
typename TagGeometry = typename geometry::tag<Geometry>::type>
-struct return_ref_or_bounds
+struct expand
+{
+ // STATIC ASSERT
+};
+
+template <typename Bounds, typename Geometry>
+struct expand<Bounds, Geometry, box_tag, point_tag>
+{
+ static inline void apply(Bounds & b, Geometry const& g)
+ {
+ geometry::expand(b, g);
+ }
+
+ template <typename Strategy>
+ static inline void apply(Bounds & b, Geometry const& g, Strategy const& )
+ {
+ geometry::expand(b, g, typename Strategy::expand_point_strategy_type());
+ }
+};
+
+template <typename Bounds, typename Geometry>
+struct expand<Bounds, Geometry, box_tag, box_tag>
+{
+ static inline void apply(Bounds & b, Geometry const& g)
+ {
+ geometry::expand(b, g);
+ }
+
+ template <typename Strategy>
+ static inline void apply(Bounds & b, Geometry const& g, Strategy const& )
+ {
+ geometry::expand(b, g, typename Strategy::expand_box_strategy_type());
+ }
+};
+
+template <typename Bounds, typename Geometry>
+struct expand<Bounds, Geometry, box_tag, segment_tag>
+{
+ static inline void apply(Bounds & b, Geometry const& g)
+ {
+ geometry::expand(b, g);
+ }
+
+ template <typename Strategy>
+ static inline void apply(Bounds & b, Geometry const& g, Strategy const& s)
+ {
+ index::detail::bounded_view<Geometry, Bounds, Strategy> v(g, s);
+ geometry::expand(b, v, typename Strategy::expand_box_strategy_type());
+ }
+};
+
+
+} // namespace dispatch
+
+
+template <typename Bounds, typename Geometry, typename Strategy>
+inline void expand(Bounds & b, Geometry const& g, Strategy const& s)
{
- typedef Geometry const& result_type;
+ dispatch::expand<Bounds, Geometry>::apply(b, g, s);
+}
+
+template <typename Bounds, typename Geometry>
+inline void expand(Bounds & b, Geometry const& g, default_strategy const& )
+{
+ dispatch::expand<Bounds, Geometry>::apply(b, g);
+}
+
+
+namespace dispatch
+{
+
+
+template <typename Geometry,
+ typename Bounds,
+ typename TagGeometry = typename geometry::tag<Geometry>::type,
+ typename TagBounds = typename geometry::tag<Bounds>::type>
+struct covered_by_bounds
+{};
+
+template <typename Geometry, typename Bounds>
+struct covered_by_bounds<Geometry, Bounds, point_tag, box_tag>
+{
+ static inline bool apply(Geometry const& g, Bounds & b)
+ {
+ return geometry::covered_by(g, b);
+ }
+
+ template <typename Strategy>
+ static inline bool apply(Geometry const& g, Bounds & b, Strategy const&)
+ {
+ return geometry::covered_by(g, b, typename Strategy::covered_by_point_box_strategy_type());
+ }
+};
+
+template <typename Geometry, typename Bounds>
+struct covered_by_bounds<Geometry, Bounds, box_tag, box_tag>
+{
+ static inline bool apply(Geometry const& g, Bounds & b)
+ {
+ return geometry::covered_by(g, b);
+ }
- static inline result_type apply(Geometry const& g)
+ template <typename Strategy>
+ static inline bool apply(Geometry const& g, Bounds & b, Strategy const&)
{
- return g;
+ return geometry::covered_by(g, b, typename Strategy::covered_by_box_box_strategy_type());
}
};
-template <typename Geometry>
-struct return_ref_or_bounds<Geometry, segment_tag>
+template <typename Geometry, typename Bounds>
+struct covered_by_bounds<Geometry, Bounds, segment_tag, box_tag>
{
- typedef typename point_type<Geometry>::type point_type;
- typedef geometry::model::box<point_type> bounds_type;
- typedef index::detail::bounded_view<Geometry, bounds_type> result_type;
+ static inline bool apply(Geometry const& g, Bounds & b)
+ {
+ typedef typename point_type<Geometry>::type point_type;
+ typedef geometry::model::box<point_type> bounds_type;
+ typedef index::detail::bounded_view<Geometry, bounds_type, default_strategy> view_type;
+
+ return geometry::covered_by(view_type(g, default_strategy()), b);
+ }
- static inline result_type apply(Geometry const& g)
+ template <typename Strategy>
+ static inline bool apply(Geometry const& g, Bounds & b, Strategy const& strategy)
{
- return result_type(g);
+ typedef typename point_type<Geometry>::type point_type;
+ typedef geometry::model::box<point_type> bounds_type;
+ typedef index::detail::bounded_view<Geometry, bounds_type, Strategy> view_type;
+
+ return geometry::covered_by(view_type(g, strategy), b,
+ typename Strategy::covered_by_box_box_strategy_type());
}
};
+
} // namespace dispatch
-template <typename Geometry>
-inline
-typename dispatch::return_ref_or_bounds<Geometry>::result_type
-return_ref_or_bounds(Geometry const& g)
+
+template <typename Geometry, typename Bounds, typename Strategy>
+inline bool covered_by_bounds(Geometry const& g, Bounds & b, Strategy const& s)
+{
+ return dispatch::covered_by_bounds<Geometry, Bounds>::apply(g, b, s);
+}
+
+template <typename Geometry, typename Bounds>
+inline bool covered_by_bounds(Geometry const& g, Bounds & b, default_strategy const& )
{
- return dispatch::return_ref_or_bounds<Geometry>::apply(g);
+ return dispatch::covered_by_bounds<Geometry, Bounds>::apply(g, b);
}
+
}}}} // namespace boost::geometry::index::detail
+
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP
diff --git a/boost/geometry/index/detail/algorithms/intersection_content.hpp b/boost/geometry/index/detail/algorithms/intersection_content.hpp
index b8ef9e7163..2fee7b13dd 100644
--- a/boost/geometry/index/detail/algorithms/intersection_content.hpp
+++ b/boost/geometry/index/detail/algorithms/intersection_content.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -18,18 +22,32 @@
namespace boost { namespace geometry { namespace index { namespace detail {
+// Util to distinguish between default and non-default index strategy
+template <typename Box, typename Strategy>
+inline bool disjoint_box_box(Box const& box1, Box const& box2, Strategy const&)
+{
+ return geometry::detail::disjoint::disjoint_box_box(box1, box2,
+ typename Strategy::disjoint_box_box_strategy_type());
+}
+
+template <typename Box>
+inline bool disjoint_box_box(Box const& box1, Box const& box2, default_strategy const& )
+{
+ typedef typename strategy::disjoint::services::default_strategy<Box, Box>::type strategy_type;
+ return geometry::detail::disjoint::disjoint_box_box(box1, box2, strategy_type());
+}
+
/**
- * \brief Compute the area of the intersection of b1 and b2
+ * \brief Compute the area, volume, ... of the intersection of b1 and b2
*/
-template <typename Box>
-inline typename default_content_result<Box>::type intersection_content(Box const& box1, Box const& box2)
+template <typename Box, typename Strategy>
+inline typename default_content_result<Box>::type intersection_content(Box const& box1, Box const& box2, Strategy const& strategy)
{
- typedef typename strategy::disjoint::services::default_strategy
- <
- Box, Box
- >::type strategy_type;
+ bool const intersects = ! index::detail::disjoint_box_box(box1, box2, strategy);
- bool const intersects = ! geometry::detail::disjoint::disjoint_box_box(box1, box2, strategy_type());
+ // NOTE: the code below may be inconsistent with the disjoint_box_box()
+ // however intersection_box_box checks if the boxes intersect on the fly so it should be ok
+ // but this also means that disjoint_box_box() is probably not needed
if ( intersects )
{
@@ -46,6 +64,12 @@ inline typename default_content_result<Box>::type intersection_content(Box const
return 0;
}
+template <typename Box>
+inline typename default_content_result<Box>::type intersection_content(Box const& box1, Box const& box2)
+{
+ return intersection_content(box1, box2, default_strategy());
+}
+
}}}} // namespace boost::geometry::index::detail
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP
diff --git a/boost/geometry/index/detail/bounded_view.hpp b/boost/geometry/index/detail/bounded_view.hpp
index e5f489d76b..f6df2fa79b 100644
--- a/boost/geometry/index/detail/bounded_view.hpp
+++ b/boost/geometry/index/detail/bounded_view.hpp
@@ -5,6 +5,10 @@
//
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -12,35 +16,59 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP
+#include <boost/mpl/assert.hpp>
+
#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/strategies/index.hpp>
+
namespace boost { namespace geometry {
namespace index { namespace detail {
-template <typename Geometry,
- typename BoundingGeometry,
- typename Tag = typename geometry::tag<Geometry>::type,
- typename BoundingTag = typename geometry::tag<BoundingGeometry>::type,
- typename CSystem = typename geometry::coordinate_system<Geometry>::type>
-struct bounded_view
+
+template <typename Geometry, typename BoundingGeometry, typename Strategy>
+struct bounded_view_base_cs_tag
+{
+ typedef typename Strategy::cs_tag type;
+};
+
+template <typename Geometry, typename BoundingGeometry>
+struct bounded_view_base_cs_tag<Geometry, BoundingGeometry, default_strategy>
+ : geometry::cs_tag<Geometry>
+{};
+
+
+template
+<
+ typename Geometry,
+ typename BoundingGeometry,
+ typename Strategy,
+ typename Tag = typename geometry::tag<Geometry>::type,
+ typename BoundingTag = typename geometry::tag<BoundingGeometry>::type,
+ typename CSTag = typename bounded_view_base_cs_tag
+ <
+ Geometry, BoundingGeometry, Strategy
+ >::type
+>
+struct bounded_view_base
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THOSE_GEOMETRIES,
- (BoundingTag, Tag));
+ (types<Tag, BoundingTag, CSTag>));
};
// Segment -> Box
-template <typename Segment, typename Box>
-struct bounded_view<Segment, Box, segment_tag, box_tag, cs::cartesian>
+template <typename Segment, typename Box, typename Strategy>
+struct bounded_view_base<Segment, Box, Strategy, segment_tag, box_tag, cartesian_tag>
{
public:
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
- explicit bounded_view(Segment const& segment)
+ bounded_view_base(Segment const& segment, Strategy const& )
: m_segment(segment)
{}
@@ -64,15 +92,27 @@ private:
Segment const& m_segment;
};
-template <typename Segment, typename Box, typename CSystem>
-struct bounded_view<Segment, Box, segment_tag, box_tag, CSystem>
+template <typename Segment, typename Box, typename Strategy, typename CSTag>
+struct bounded_view_base<Segment, Box, Strategy, segment_tag, box_tag, CSTag>
{
+ template <typename S>
+ inline void envelope(Segment const& segment, S const& strategy)
+ {
+ geometry::envelope(segment, m_box,
+ strategy.get_envelope_segment_strategy());
+ }
+
+ inline void envelope(Segment const& segment, default_strategy const& )
+ {
+ geometry::envelope(segment, m_box);
+ }
+
public:
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
- explicit bounded_view(Segment const& segment)
+ bounded_view_base(Segment const& segment, Strategy const& strategy)
{
- geometry::envelope(segment, m_box);
+ envelope(segment, strategy);
}
template <std::size_t Dimension>
@@ -93,13 +133,13 @@ private:
// Box -> Box
-template <typename BoxIn, typename Box, typename CSystem>
-struct bounded_view<BoxIn, Box, box_tag, box_tag, CSystem>
+template <typename BoxIn, typename Box, typename Strategy, typename CSTag>
+struct bounded_view_base<BoxIn, Box, Strategy, box_tag, box_tag, CSTag>
{
public:
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
- explicit bounded_view(BoxIn const& box)
+ bounded_view_base(BoxIn const& box, Strategy const& )
: m_box(box)
{}
@@ -123,13 +163,13 @@ private:
// Point -> Box
-template <typename Point, typename Box, typename CSystem>
-struct bounded_view<Point, Box, point_tag, box_tag, CSystem>
+template <typename Point, typename Box, typename Strategy, typename CSTag>
+struct bounded_view_base<Point, Box, Strategy, point_tag, box_tag, CSTag>
{
public:
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
- explicit bounded_view(Point const& point)
+ bounded_view_base(Point const& point, Strategy const& )
: m_point(point)
{}
@@ -151,6 +191,52 @@ private:
Point const& m_point;
};
+
+template <typename Geometry,
+ typename BoundingGeometry,
+ typename Strategy,
+ typename Tag = typename geometry::tag<Geometry>::type,
+ typename BoundingTag = typename geometry::tag<BoundingGeometry>::type>
+struct bounded_view
+ : bounded_view_base<Geometry, BoundingGeometry, Strategy>
+{
+ typedef bounded_view_base<Geometry, BoundingGeometry, Strategy> base_type;
+
+ bounded_view(Geometry const& geometry, Strategy const& strategy)
+ : base_type(geometry, strategy)
+ {}
+};
+
+template <typename Geometry,
+ typename BoundingGeometry,
+ typename Tag,
+ typename BoundingTag>
+struct bounded_view<Geometry, BoundingGeometry, default_strategy, Tag, BoundingTag>
+ : bounded_view_base
+ <
+ Geometry,
+ BoundingGeometry,
+ typename strategy::index::services::default_strategy<Geometry>::type
+ >
+{
+ typedef typename strategy::index::services::default_strategy
+ <
+ Geometry
+ >::type strategy_type;
+
+ typedef bounded_view_base
+ <
+ Geometry,
+ BoundingGeometry,
+ strategy_type
+ > base_type;
+
+ explicit bounded_view(Geometry const& geometry, default_strategy const& )
+ : base_type(geometry, strategy_type())
+ {}
+};
+
+
}} // namespace index::detail
// XXX -> Box
@@ -159,23 +245,23 @@ private:
namespace traits
{
-template <typename Geometry, typename Box, typename Tag, typename CSystem>
-struct tag< index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> >
+template <typename Geometry, typename Box, typename Strategy, typename Tag>
+struct tag< index::detail::bounded_view<Geometry, Box, Strategy, Tag, box_tag> >
{
typedef box_tag type;
};
-template <typename Geometry, typename Box, typename Tag, typename CSystem>
-struct point_type< index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> >
+template <typename Geometry, typename Box, typename Strategy, typename Tag>
+struct point_type< index::detail::bounded_view<Geometry, Box, Strategy, Tag, box_tag> >
{
typedef typename point_type<Box>::type type;
};
-template <typename Geometry, typename Box, typename Tag, typename CSystem, std::size_t Dimension>
-struct indexed_access<index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem>,
+template <typename Geometry, typename Box, typename Strategy, typename Tag, std::size_t Dimension>
+struct indexed_access<index::detail::bounded_view<Geometry, Box, Strategy, Tag, box_tag>,
min_corner, Dimension>
{
- typedef index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> box_type;
+ typedef index::detail::bounded_view<Geometry, Box, Strategy, Tag, box_tag> box_type;
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
static inline coordinate_type get(box_type const& b)
@@ -189,11 +275,11 @@ struct indexed_access<index::detail::bounded_view<Geometry, Box, Tag, box_tag, C
//}
};
-template <typename Geometry, typename Box, typename Tag, typename CSystem, std::size_t Dimension>
-struct indexed_access<index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem>,
+template <typename Geometry, typename Box, typename Strategy, typename Tag, std::size_t Dimension>
+struct indexed_access<index::detail::bounded_view<Geometry, Box, Strategy, Tag, box_tag>,
max_corner, Dimension>
{
- typedef index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> box_type;
+ typedef index::detail::bounded_view<Geometry, Box, Strategy, Tag, box_tag> box_type;
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
static inline coordinate_type get(box_type const& b)
diff --git a/boost/geometry/index/detail/distance_predicates.hpp b/boost/geometry/index/detail/distance_predicates.hpp
index 9a9371df95..446797450a 100644
--- a/boost/geometry/index/detail/distance_predicates.hpp
+++ b/boost/geometry/index/detail/distance_predicates.hpp
@@ -5,6 +5,10 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -93,64 +97,211 @@ struct relation< to_furthest<T> >
};
// ------------------------------------------------------------------ //
+
+template
+<
+ typename G1, typename G2, typename Strategy,
+ typename Tag1 = typename geometry::tag<G1>::type,
+ typename Tag2 = typename geometry::tag<G2>::type
+>
+struct comparable_distance_call_base
+{
+ typedef typename geometry::default_comparable_distance_result
+ <
+ G1, G2
+ >::type result_type;
+
+ static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const&)
+ {
+ return geometry::comparable_distance(g1, g2);
+ }
+};
+
+template
+<
+ typename G1, typename G2, typename Strategy
+>
+struct comparable_distance_call_base<G1, G2, Strategy, point_tag, point_tag>
+{
+ typedef typename geometry::comparable_distance_result
+ <
+ G1, G2,
+ typename Strategy::comparable_distance_point_point_strategy_type
+ >::type result_type;
+
+ static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s)
+ {
+ return geometry::comparable_distance(g1, g2,
+ s.get_comparable_distance_point_point_strategy());
+ }
+};
+
+template
+<
+ typename G1, typename G2, typename Strategy
+>
+struct comparable_distance_call_base<G1, G2, Strategy, point_tag, box_tag>
+{
+ typedef typename geometry::comparable_distance_result
+ <
+ G1, G2,
+ typename Strategy::comparable_distance_point_box_strategy_type
+ >::type result_type;
+
+ static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s)
+ {
+ return geometry::comparable_distance(g1, g2,
+ s.get_comparable_distance_point_box_strategy());
+ }
+};
+
+template
+<
+ typename G1, typename G2, typename Strategy
+>
+struct comparable_distance_call_base<G1, G2, Strategy, segment_tag, point_tag>
+{
+ typedef typename geometry::comparable_distance_result
+ <
+ G1, G2,
+ typename Strategy::comparable_distance_point_segment_strategy_type
+ >::type result_type;
+
+ static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s)
+ {
+ return geometry::comparable_distance(g1, g2,
+ s.get_comparable_distance_point_segment_strategy());
+ }
+};
+
+template
+<
+ typename G1, typename G2, typename Strategy
+>
+struct comparable_distance_call_base<G1, G2, Strategy, segment_tag, box_tag>
+{
+ typedef typename geometry::comparable_distance_result
+ <
+ G1, G2,
+ typename Strategy::comparable_distance_segment_box_strategy_type
+ >::type result_type;
+
+ static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s)
+ {
+ return geometry::comparable_distance(g1, g2,
+ s.get_comparable_distance_segment_box_strategy());
+ }
+};
+
+template
+<
+ typename G1, typename G2, typename Strategy
+>
+struct comparable_distance_call_base<G1, G2, Strategy, segment_tag, segment_tag>
+{
+ typedef typename geometry::comparable_distance_result
+ <
+ G1, G2,
+ typename Strategy::comparable_distance_point_segment_strategy_type
+ >::type result_type;
+
+ static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s)
+ {
+ return geometry::comparable_distance(g1, g2,
+ s.get_comparable_distance_point_segment_strategy());
+ }
+};
+
+template
+<
+ typename G1, typename G2, typename Strategy
+>
+struct comparable_distance_call
+ : comparable_distance_call_base<G1, G2, Strategy>
+{};
+
+template
+<
+ typename G1, typename G2
+>
+struct comparable_distance_call<G1, G2, default_strategy>
+ : comparable_distance_call_base<G1, G2, default_strategy, void, void>
+{};
+
+// ------------------------------------------------------------------ //
// calculate_distance
// ------------------------------------------------------------------ //
-template <typename Predicate, typename Indexable, typename Tag>
+template <typename Predicate, typename Indexable, typename Strategy, typename Tag>
struct calculate_distance
{
BOOST_MPL_ASSERT_MSG((false), INVALID_PREDICATE_OR_TAG, (calculate_distance));
};
// this handles nearest() with default Point parameter, to_nearest() and bounds
-template <typename PointRelation, typename Indexable, typename Tag>
-struct calculate_distance< predicates::nearest<PointRelation>, Indexable, Tag >
+template <typename PointRelation, typename Indexable, typename Strategy, typename Tag>
+struct calculate_distance< predicates::nearest<PointRelation>, Indexable, Strategy, Tag>
{
typedef detail::relation<PointRelation> relation;
- typedef typename relation::value_type point_type;
- typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;
+ typedef comparable_distance_call
+ <
+ typename relation::value_type,
+ Indexable,
+ Strategy
+ > call_type;
+ typedef typename call_type::result_type result_type;
- static inline bool apply(predicates::nearest<PointRelation> const& p, Indexable const& i, result_type & result)
+ static inline bool apply(predicates::nearest<PointRelation> const& p, Indexable const& i,
+ Strategy const& s, result_type & result)
{
- result = geometry::comparable_distance(relation::value(p.point_or_relation), i);
+ result = call_type::apply(relation::value(p.point_or_relation), i, s);
return true;
}
};
-template <typename Point, typename Indexable>
-struct calculate_distance< predicates::nearest< to_centroid<Point> >, Indexable, value_tag>
+template <typename Point, typename Indexable, typename Strategy>
+struct calculate_distance< predicates::nearest< to_centroid<Point> >, Indexable, Strategy, value_tag>
{
typedef Point point_type;
- typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;
+ typedef typename geometry::default_comparable_distance_result
+ <
+ point_type, Indexable
+ >::type result_type;
- static inline bool apply(predicates::nearest< to_centroid<Point> > const& p, Indexable const& i, result_type & result)
+ static inline bool apply(predicates::nearest< to_centroid<Point> > const& p, Indexable const& i,
+ Strategy const& , result_type & result)
{
result = index::detail::comparable_distance_centroid(p.point_or_relation.value, i);
return true;
}
};
-template <typename Point, typename Indexable>
-struct calculate_distance< predicates::nearest< to_furthest<Point> >, Indexable, value_tag>
+template <typename Point, typename Indexable, typename Strategy>
+struct calculate_distance< predicates::nearest< to_furthest<Point> >, Indexable, Strategy, value_tag>
{
typedef Point point_type;
- typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;
+ typedef typename geometry::default_comparable_distance_result
+ <
+ point_type, Indexable
+ >::type result_type;
- static inline bool apply(predicates::nearest< to_furthest<Point> > const& p, Indexable const& i, result_type & result)
+ static inline bool apply(predicates::nearest< to_furthest<Point> > const& p, Indexable const& i,
+ Strategy const& , result_type & result)
{
result = index::detail::comparable_distance_far(p.point_or_relation.value, i);
return true;
}
};
-template <typename SegmentOrLinestring, typename Indexable, typename Tag>
-struct calculate_distance< predicates::path<SegmentOrLinestring>, Indexable, Tag>
+template <typename SegmentOrLinestring, typename Indexable, typename Strategy, typename Tag>
+struct calculate_distance< predicates::path<SegmentOrLinestring>, Indexable, Strategy, Tag>
{
typedef typename index::detail::default_path_intersection_distance_type<
Indexable, SegmentOrLinestring
>::type result_type;
- static inline bool apply(predicates::path<SegmentOrLinestring> const& p, Indexable const& i, result_type & result)
+ static inline bool apply(predicates::path<SegmentOrLinestring> const& p, Indexable const& i,
+ Strategy const& , result_type & result)
{
return index::detail::path_intersection(i, p.geometry, result);
}
diff --git a/boost/geometry/index/detail/predicates.hpp b/boost/geometry/index/detail/predicates.hpp
index 72c6c661b7..ba564f8c58 100644
--- a/boost/geometry/index/detail/predicates.hpp
+++ b/boost/geometry/index/detail/predicates.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -128,8 +132,8 @@ struct predicate_check
template <typename Fun>
struct predicate_check<predicates::satisfies<Fun, false>, value_tag>
{
- template <typename Value, typename Indexable>
- static inline bool apply(predicates::satisfies<Fun, false> const& p, Value const& v, Indexable const&)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(predicates::satisfies<Fun, false> const& p, Value const& v, Indexable const& , Strategy const&)
{
return p.fun(v);
}
@@ -138,8 +142,8 @@ struct predicate_check<predicates::satisfies<Fun, false>, value_tag>
template <typename Fun>
struct predicate_check<predicates::satisfies<Fun, true>, value_tag>
{
- template <typename Value, typename Indexable>
- static inline bool apply(predicates::satisfies<Fun, true> const& p, Value const& v, Indexable const&)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(predicates::satisfies<Fun, true> const& p, Value const& v, Indexable const& , Strategy const&)
{
return !p.fun(v);
}
@@ -156,8 +160,8 @@ struct spatial_predicate_call
template <>
struct spatial_predicate_call<predicates::contains_tag>
{
- template <typename G1, typename G2>
- static inline bool apply(G1 const& g1, G2 const& g2)
+ template <typename G1, typename G2, typename S>
+ static inline bool apply(G1 const& g1, G2 const& g2, S const&)
{
return geometry::within(g2, g1);
}
@@ -166,8 +170,8 @@ struct spatial_predicate_call<predicates::contains_tag>
template <>
struct spatial_predicate_call<predicates::covered_by_tag>
{
- template <typename G1, typename G2>
- static inline bool apply(G1 const& g1, G2 const& g2)
+ template <typename G1, typename G2, typename S>
+ static inline bool apply(G1 const& g1, G2 const& g2, S const&)
{
return geometry::covered_by(g1, g2);
}
@@ -176,8 +180,8 @@ struct spatial_predicate_call<predicates::covered_by_tag>
template <>
struct spatial_predicate_call<predicates::covers_tag>
{
- template <typename G1, typename G2>
- static inline bool apply(G1 const& g1, G2 const& g2)
+ template <typename G1, typename G2, typename S>
+ static inline bool apply(G1 const& g1, G2 const& g2, S const&)
{
return geometry::covered_by(g2, g1);
}
@@ -186,28 +190,60 @@ struct spatial_predicate_call<predicates::covers_tag>
template <>
struct spatial_predicate_call<predicates::disjoint_tag>
{
- template <typename G1, typename G2>
- static inline bool apply(G1 const& g1, G2 const& g2)
+ template <typename G1, typename G2, typename S>
+ static inline bool apply(G1 const& g1, G2 const& g2, S const&)
{
return geometry::disjoint(g1, g2);
}
};
+// TEMP: used to implement CS-specific intersects predicate for certain
+// combinations of geometries until umbrella strategies are implemented
+template
+<
+ typename G1, typename G2,
+ typename Tag1 = typename tag<G1>::type,
+ typename Tag2 = typename tag<G2>::type
+>
+struct spatial_predicate_intersects
+{
+ template <typename S>
+ static inline bool apply(G1 const& g1, G2 const& g2, S const&)
+ {
+ return geometry::intersects(g1, g2);
+ }
+};
+// TEMP: used in within and relate
+template <typename G1, typename G2>
+struct spatial_predicate_intersects<G1, G2, box_tag, point_tag>
+{
+ static inline bool apply(G1 const& g1, G2 const& g2, default_strategy const&)
+ {
+ return geometry::intersects(g1, g2);
+ }
+
+ template <typename S>
+ static inline bool apply(G1 const& g1, G2 const& g2, S const& )
+ {
+ return geometry::intersects(g1, g2, typename S::covered_by_point_box_strategy_type());
+ }
+};
+
template <>
struct spatial_predicate_call<predicates::intersects_tag>
{
- template <typename G1, typename G2>
- static inline bool apply(G1 const& g1, G2 const& g2)
+ template <typename G1, typename G2, typename S>
+ static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
{
- return geometry::intersects(g1, g2);
+ return spatial_predicate_intersects<G1, G2>::apply(g1, g2, s);
}
};
template <>
struct spatial_predicate_call<predicates::overlaps_tag>
{
- template <typename G1, typename G2>
- static inline bool apply(G1 const& g1, G2 const& g2)
+ template <typename G1, typename G2, typename S>
+ static inline bool apply(G1 const& g1, G2 const& g2, S const&)
{
return geometry::overlaps(g1, g2);
}
@@ -216,8 +252,8 @@ struct spatial_predicate_call<predicates::overlaps_tag>
template <>
struct spatial_predicate_call<predicates::touches_tag>
{
- template <typename G1, typename G2>
- static inline bool apply(G1 const& g1, G2 const& g2)
+ template <typename G1, typename G2, typename S>
+ static inline bool apply(G1 const& g1, G2 const& g2, S const&)
{
return geometry::touches(g1, g2);
}
@@ -226,8 +262,8 @@ struct spatial_predicate_call<predicates::touches_tag>
template <>
struct spatial_predicate_call<predicates::within_tag>
{
- template <typename G1, typename G2>
- static inline bool apply(G1 const& g1, G2 const& g2)
+ template <typename G1, typename G2, typename S>
+ static inline bool apply(G1 const& g1, G2 const& g2, S const&)
{
return geometry::within(g1, g2);
}
@@ -241,10 +277,10 @@ struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, valu
{
typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
{
- return spatial_predicate_call<Tag>::apply(i, p.geometry);
+ return spatial_predicate_call<Tag>::apply(i, p.geometry, s);
}
};
@@ -254,10 +290,10 @@ struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, value
{
typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
{
- return !spatial_predicate_call<Tag>::apply(i, p.geometry);
+ return !spatial_predicate_call<Tag>::apply(i, p.geometry, s);
}
};
@@ -266,8 +302,8 @@ struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, value
template <typename DistancePredicates>
struct predicate_check<predicates::nearest<DistancePredicates>, value_tag>
{
- template <typename Value, typename Box>
- static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&)
+ template <typename Value, typename Box, typename Strategy>
+ static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&, Strategy const&)
{
return true;
}
@@ -276,8 +312,8 @@ struct predicate_check<predicates::nearest<DistancePredicates>, value_tag>
template <typename Linestring>
struct predicate_check<predicates::path<Linestring>, value_tag>
{
- template <typename Value, typename Box>
- static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&)
+ template <typename Value, typename Box, typename Strategy>
+ static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&, Strategy const&)
{
return true;
}
@@ -290,8 +326,8 @@ struct predicate_check<predicates::path<Linestring>, value_tag>
template <typename Fun, bool Negated>
struct predicate_check<predicates::satisfies<Fun, Negated>, bounds_tag>
{
- template <typename Value, typename Box>
- static bool apply(predicates::satisfies<Fun, Negated> const&, Value const&, Box const&)
+ template <typename Value, typename Box, typename Strategy>
+ static bool apply(predicates::satisfies<Fun, Negated> const&, Value const&, Box const&, Strategy const&)
{
return true;
}
@@ -317,10 +353,10 @@ struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, boun
{
typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
{
- return spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);
+ return spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry, s);
}
};
@@ -330,10 +366,10 @@ struct predicate_check<predicates::spatial_predicate<Geometry, predicates::conta
{
typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, false> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
{
- return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry);
+ return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry, s);
}
};
@@ -343,10 +379,10 @@ struct predicate_check<predicates::spatial_predicate<Geometry, predicates::cover
{
typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, false> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
{
- return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry);
+ return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry, s);
}
};
@@ -356,10 +392,10 @@ struct predicate_check<predicates::spatial_predicate<Geometry, predicates::disjo
{
typedef predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
{
- return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry);
+ return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry, s);
}
};
@@ -381,10 +417,10 @@ struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, bound
{
typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
{
- return !spatial_predicate_call<Tag>::apply(i, p.geometry);
+ return !spatial_predicate_call<Tag>::apply(i, p.geometry, s);
}
};
@@ -394,8 +430,8 @@ struct predicate_check<predicates::spatial_predicate<Geometry, predicates::conta
{
typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, true> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& , Value const&, Indexable const& )
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
{
return true;
}
@@ -407,8 +443,8 @@ struct predicate_check<predicates::spatial_predicate<Geometry, predicates::cover
{
typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, true> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& , Value const&, Indexable const& )
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
{
return true;
}
@@ -420,10 +456,10 @@ struct predicate_check<predicates::spatial_predicate<Geometry, predicates::inter
{
typedef predicates::spatial_predicate<Geometry, predicates::intersects_tag, true> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
{
- return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry);
+ return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry, s);
}
};
@@ -433,8 +469,8 @@ struct predicate_check<predicates::spatial_predicate<Geometry, predicates::overl
{
typedef predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& , Value const&, Indexable const& )
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
{
return true;
}
@@ -446,8 +482,8 @@ struct predicate_check<predicates::spatial_predicate<Geometry, predicates::touch
{
typedef predicates::spatial_predicate<Geometry, predicates::touches_tag, true> Pred;
- template <typename Value, typename Indexable>
- static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const&)
{
return !spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);
}
@@ -458,8 +494,8 @@ struct predicate_check<predicates::spatial_predicate<Geometry, predicates::touch
template <typename DistancePredicates>
struct predicate_check<predicates::nearest<DistancePredicates>, bounds_tag>
{
- template <typename Value, typename Box>
- static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&)
+ template <typename Value, typename Box, typename Strategy>
+ static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&, Strategy const&)
{
return true;
}
@@ -468,8 +504,8 @@ struct predicate_check<predicates::nearest<DistancePredicates>, bounds_tag>
template <typename Linestring>
struct predicate_check<predicates::path<Linestring>, bounds_tag>
{
- template <typename Value, typename Box>
- static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&)
+ template <typename Value, typename Box, typename Strategy>
+ static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&, Strategy const&)
{
return true;
}
@@ -600,23 +636,23 @@ struct predicates_element< I, boost::tuples::cons<Head, Tail> >
template <typename TuplePredicates, typename Tag, unsigned First, unsigned Last>
struct predicates_check_tuple
{
- template <typename Value, typename Indexable>
- static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i, Strategy const& s)
{
- return
- predicate_check<
- typename boost::tuples::element<First, TuplePredicates>::type,
- Tag
- >::apply(boost::get<First>(p), v, i) &&
- predicates_check_tuple<TuplePredicates, Tag, First+1, Last>::apply(p, v, i);
+ return predicate_check
+ <
+ typename boost::tuples::element<First, TuplePredicates>::type,
+ Tag
+ >::apply(boost::get<First>(p), v, i, s)
+ && predicates_check_tuple<TuplePredicates, Tag, First+1, Last>::apply(p, v, i, s);
}
};
template <typename TuplePredicates, typename Tag, unsigned First>
struct predicates_check_tuple<TuplePredicates, Tag, First, First>
{
- template <typename Value, typename Indexable>
- static inline bool apply(TuplePredicates const& , Value const& , Indexable const& )
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(TuplePredicates const& , Value const& , Indexable const& , Strategy const& )
{
return true;
}
@@ -628,10 +664,10 @@ struct predicates_check_impl
static const bool check = First < 1 && Last <= 1 && First <= Last;
BOOST_MPL_ASSERT_MSG((check), INVALID_INDEXES, (predicates_check_impl));
- template <typename Value, typename Indexable>
- static inline bool apply(Predicate const& p, Value const& v, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(Predicate const& p, Value const& v, Indexable const& i, Strategy const& s)
{
- return predicate_check<Predicate, Tag>::apply(p, v, i);
+ return predicate_check<Predicate, Tag>::apply(p, v, i, s);
}
};
@@ -685,21 +721,21 @@ struct predicates_check_impl<
static const bool check = First < pred_len && Last <= pred_len && First <= Last;
BOOST_MPL_ASSERT_MSG((check), INVALID_INDEXES, (predicates_check_impl));
- template <typename Value, typename Indexable>
- static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i)
+ template <typename Value, typename Indexable, typename Strategy>
+ static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i, Strategy const& s)
{
return predicates_check_tuple<
predicates_type,
Tag, First, Last
- >::apply(p, v, i);
+ >::apply(p, v, i, s);
}
};
-template <typename Tag, unsigned First, unsigned Last, typename Predicates, typename Value, typename Indexable>
-inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i)
+template <typename Tag, unsigned First, unsigned Last, typename Predicates, typename Value, typename Indexable, typename Strategy>
+inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i, Strategy const& s)
{
return detail::predicates_check_impl<Predicates, Tag, First, Last>
- ::apply(p, v, i);
+ ::apply(p, v, i, s);
}
// ------------------------------------------------------------------ //
diff --git a/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp
index c794a64267..a0635acab1 100644
--- a/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp
+++ b/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp
@@ -5,6 +5,10 @@
// Copyright (c) 2008 Federico J. Fernandez.
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -15,6 +19,7 @@
#include <boost/core/ignore_unused.hpp>
#include <boost/type_traits/is_unsigned.hpp>
+#include <boost/geometry/index/detail/algorithms/bounds.hpp>
#include <boost/geometry/index/detail/algorithms/content.hpp>
#include <boost/geometry/index/detail/bounded_view.hpp>
@@ -90,7 +95,11 @@ struct find_greatest_normalized_separation
typedef typename geometry::point_type<indexable_type>::type point_type;
typedef geometry::model::box<point_type> bounds_type;
- typedef index::detail::bounded_view<indexable_type, bounds_type> bounded_view_type;
+ typedef index::detail::bounded_view
+ <
+ indexable_type, bounds_type,
+ typename index::detail::strategy_type<Parameters>::type
+ > bounded_view_type;
static inline void apply(Elements const& elements,
Parameters const& parameters,
@@ -103,8 +112,12 @@ struct find_greatest_normalized_separation
BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected number of elements");
BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements");
+ typename index::detail::strategy_type<Parameters>::type const&
+ strategy = index::detail::get_strategy(parameters);
+
// find the lowest low, highest high
- bounded_view_type bounded_indexable_0(rtree::element_indexable(elements[0], translator));
+ bounded_view_type bounded_indexable_0(rtree::element_indexable(elements[0], translator),
+ strategy);
coordinate_type lowest_low = geometry::get<min_corner, DimensionIndex>(bounded_indexable_0);
coordinate_type highest_high = geometry::get<max_corner, DimensionIndex>(bounded_indexable_0);
@@ -113,7 +126,8 @@ struct find_greatest_normalized_separation
size_t lowest_high_index = 0;
for ( size_t i = 1 ; i < elements_count ; ++i )
{
- bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator));
+ bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator),
+ strategy);
coordinate_type min_coord = geometry::get<min_corner, DimensionIndex>(bounded_indexable);
coordinate_type max_coord = geometry::get<max_corner, DimensionIndex>(bounded_indexable);
@@ -132,11 +146,13 @@ struct find_greatest_normalized_separation
// find the highest low
size_t highest_low_index = lowest_high_index == 0 ? 1 : 0;
- bounded_view_type bounded_indexable_hl(rtree::element_indexable(elements[highest_low_index], translator));
+ bounded_view_type bounded_indexable_hl(rtree::element_indexable(elements[highest_low_index], translator),
+ strategy);
coordinate_type highest_low = geometry::get<min_corner, DimensionIndex>(bounded_indexable_hl);
for ( size_t i = highest_low_index ; i < elements_count ; ++i )
{
- bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator));
+ bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator),
+ strategy);
coordinate_type min_coord = geometry::get<min_corner, DimensionIndex>(bounded_indexable);
if ( highest_low < min_coord &&
i != lowest_high_index )
@@ -329,6 +345,9 @@ struct redistribute_elements<Value, Options, Translator, Box, Allocators, linear
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
typedef typename index::detail::default_content_result<Box>::type content_type;
+ typename index::detail::strategy_type<parameters_type>::type const&
+ strategy = index::detail::get_strategy(parameters);
+
elements_type & elements1 = rtree::elements(n);
elements_type & elements2 = rtree::elements(second_node);
const size_t elements1_count = parameters.get_max_elements() + 1;
@@ -357,8 +376,10 @@ struct redistribute_elements<Value, Options, Translator, Box, Allocators, linear
elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy)
// calculate boxes
- detail::bounds(rtree::element_indexable(elements_copy[seed1], translator), box1);
- detail::bounds(rtree::element_indexable(elements_copy[seed2], translator), box2);
+ detail::bounds(rtree::element_indexable(elements_copy[seed1], translator),
+ box1, strategy);
+ detail::bounds(rtree::element_indexable(elements_copy[seed2], translator),
+ box2, strategy);
// initialize areas
content_type content1 = index::detail::content(box1);
@@ -380,13 +401,13 @@ struct redistribute_elements<Value, Options, Translator, Box, Allocators, linear
if ( elements1.size() + remaining <= parameters.get_min_elements() )
{
elements1.push_back(elem); // MAY THROW, STRONG (copy)
- geometry::expand(box1, indexable);
+ index::detail::expand(box1, indexable, strategy);
content1 = index::detail::content(box1);
}
else if ( elements2.size() + remaining <= parameters.get_min_elements() )
{
elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)
- geometry::expand(box2, indexable);
+ index::detail::expand(box2, indexable, strategy);
content2 = index::detail::content(box2);
}
// choose better node and insert element
@@ -395,8 +416,8 @@ struct redistribute_elements<Value, Options, Translator, Box, Allocators, linear
// calculate enlarged boxes and areas
Box enlarged_box1(box1);
Box enlarged_box2(box2);
- geometry::expand(enlarged_box1, indexable);
- geometry::expand(enlarged_box2, indexable);
+ index::detail::expand(enlarged_box1, indexable, strategy);
+ index::detail::expand(enlarged_box2, indexable, strategy);
content_type enlarged_content1 = index::detail::content(enlarged_box1);
content_type enlarged_content2 = index::detail::content(enlarged_box2);
diff --git a/boost/geometry/index/detail/rtree/node/node.hpp b/boost/geometry/index/detail/rtree/node/node.hpp
index 2b270319f6..51ba2c7e74 100644
--- a/boost/geometry/index/detail/rtree/node/node.hpp
+++ b/boost/geometry/index/detail/rtree/node/node.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -42,8 +46,9 @@ namespace detail { namespace rtree {
// elements box
-template <typename Box, typename FwdIter, typename Translator>
-inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr)
+template <typename Box, typename FwdIter, typename Translator, typename Strategy>
+inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr,
+ Strategy const& strategy)
{
Box result;
@@ -57,11 +62,11 @@ inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr)
if ( first == last )
return result;
- detail::bounds(element_indexable(*first, tr), result);
+ detail::bounds(element_indexable(*first, tr), result, strategy);
++first;
for ( ; first != last ; ++first )
- geometry::expand(result, element_indexable(*first, tr));
+ detail::expand(result, element_indexable(*first, tr), strategy);
return result;
}
@@ -71,15 +76,16 @@ inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr)
// This ensures that leafs bounds correspond to the stored elements.
// NOTE: this is done only if the Indexable is not a Box
// in the future don't do it also for NSphere
-template <typename Box, typename FwdIter, typename Translator>
-inline Box values_box(FwdIter first, FwdIter last, Translator const& tr)
+template <typename Box, typename FwdIter, typename Translator, typename Strategy>
+inline Box values_box(FwdIter first, FwdIter last, Translator const& tr,
+ Strategy const& strategy)
{
typedef typename std::iterator_traits<FwdIter>::value_type element_type;
BOOST_MPL_ASSERT_MSG((is_leaf_element<element_type>::value),
SHOULD_BE_CALLED_ONLY_FOR_LEAF_ELEMENTS,
(element_type));
- Box result = elements_box<Box>(first, last, tr);
+ Box result = elements_box<Box>(first, last, tr, strategy);
#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
if (BOOST_GEOMETRY_CONDITION((
diff --git a/boost/geometry/index/detail/rtree/options.hpp b/boost/geometry/index/detail/rtree/options.hpp
index ff772834d7..ba104b0c29 100644
--- a/boost/geometry/index/detail/rtree/options.hpp
+++ b/boost/geometry/index/detail/rtree/options.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -148,6 +152,21 @@ struct options_type< index::dynamic_rstar >
> type;
};
+template <typename Parameters, typename Strategy>
+struct options_type< index::parameters<Parameters, Strategy> >
+ : options_type<Parameters>
+{
+ typedef typename options_type<Parameters>::type opt;
+ typedef options<
+ index::parameters<Parameters, Strategy>,
+ typename opt::insert_tag,
+ typename opt::choose_next_node_tag,
+ typename opt::split_tag,
+ typename opt::redistribute_tag,
+ typename opt::node_tag
+ > type;
+};
+
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
diff --git a/boost/geometry/index/detail/rtree/pack_create.hpp b/boost/geometry/index/detail/rtree/pack_create.hpp
index 78e4712d2f..f8565bfb3e 100644
--- a/boost/geometry/index/detail/rtree/pack_create.hpp
+++ b/boost/geometry/index/detail/rtree/pack_create.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -137,6 +141,7 @@ class pack
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
typedef typename detail::default_content_result<Box>::type content_type;
typedef typename Options::parameters_type parameters_type;
+ typedef typename detail::strategy_type<parameters_type>::type strategy_type;
static const std::size_t dimension = geometry::dimension<point_type>::value;
typedef typename rtree::container_from_elements_type<
@@ -165,7 +170,7 @@ public:
values_count = static_cast<size_type>(diff);
entries.reserve(values_count);
- expandable_box<Box> hint_box;
+ expandable_box<Box, strategy_type> hint_box(detail::get_strategy(parameters));
for ( ; first != last ; ++first )
{
// NOTE: support for iterators not returning true references adapted
@@ -194,19 +199,19 @@ public:
}
private:
- template <typename BoxType>
+ template <typename BoxType, typename Strategy>
class expandable_box
{
public:
- expandable_box()
- : m_initialized(false)
+ explicit expandable_box(Strategy const& strategy)
+ : m_strategy(strategy), m_initialized(false)
{}
template <typename Indexable>
- explicit expandable_box(Indexable const& indexable)
- : m_initialized(true)
+ explicit expandable_box(Indexable const& indexable, Strategy const& strategy)
+ : m_strategy(strategy), m_initialized(true)
{
- detail::bounds(indexable, m_box);
+ detail::bounds(indexable, m_box, m_strategy);
}
template <typename Indexable>
@@ -217,12 +222,12 @@ private:
// it's guaranteed that the Box will be initialized
// only for Points, Boxes and Segments but that's ok
// since only those Geometries can be stored
- detail::bounds(indexable, m_box);
+ detail::bounds(indexable, m_box, m_strategy);
m_initialized = true;
}
else
{
- geometry::expand(m_box, indexable);
+ detail::expand(m_box, indexable, m_strategy);
}
}
@@ -238,8 +243,9 @@ private:
}
private:
- bool m_initialized;
BoxType m_box;
+ Strategy m_strategy;
+ bool m_initialized;
};
struct subtree_elements_counts
@@ -273,7 +279,8 @@ private:
// calculate values box and copy values
// initialize the box explicitly to avoid GCC-4.4 uninitialized variable warnings with O2
- expandable_box<Box> elements_box(translator(*(first->second)));
+ expandable_box<Box, strategy_type> elements_box(translator(*(first->second)),
+ detail::get_strategy(parameters));
rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C)
for ( ++first ; first != last ; ++first )
{
@@ -319,7 +326,7 @@ private:
std::size_t nodes_count = calculate_nodes_count(values_count, subtree_counts);
rtree::elements(in).reserve(nodes_count); // MAY THROW (A)
// calculate values box and copy values
- expandable_box<Box> elements_box;
+ expandable_box<Box, strategy_type> elements_box(detail::get_strategy(parameters));
per_level_packets(first, last, hint_box, values_count, subtree_counts, next_subtree_counts,
rtree::elements(in), elements_box,
diff --git a/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp
index 1ee7554f09..3fd51d56ff 100644
--- a/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp
+++ b/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -41,12 +45,18 @@ inline void pick_seeds(Elements const& elements,
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
typedef Box box_type;
typedef typename index::detail::default_content_result<box_type>::type content_type;
- typedef index::detail::bounded_view<indexable_type, box_type> bounded_indexable_view;
+ typedef typename index::detail::strategy_type<Parameters>::type strategy_type;
+ typedef index::detail::bounded_view
+ <
+ indexable_type, box_type, strategy_type
+ > bounded_indexable_view;
const size_t elements_count = parameters.get_max_elements() + 1;
BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "wrong number of elements");
BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements");
+ strategy_type const& strategy = index::detail::get_strategy(parameters);
+
content_type greatest_free_content = 0;
seed1 = 0;
seed2 = 1;
@@ -59,11 +69,11 @@ inline void pick_seeds(Elements const& elements,
indexable_type const& ind2 = rtree::element_indexable(elements[j], tr);
box_type enlarged_box;
- detail::bounds(ind1, enlarged_box);
- geometry::expand(enlarged_box, ind2);
+ index::detail::bounds(ind1, enlarged_box, strategy);
+ index::detail::expand(enlarged_box, ind2, strategy);
- bounded_indexable_view bounded_ind1(ind1);
- bounded_indexable_view bounded_ind2(ind2);
+ bounded_indexable_view bounded_ind1(ind1, strategy);
+ bounded_indexable_view bounded_ind2(ind2, strategy);
content_type free_content = ( index::detail::content(enlarged_box)
- index::detail::content(bounded_ind1) )
- index::detail::content(bounded_ind2);
@@ -129,13 +139,18 @@ struct redistribute_elements<Value, Options, Translator, Box, Allocators, quadra
BOOST_TRY
{
+ typename index::detail::strategy_type<parameters_type>::type const&
+ strategy = index::detail::get_strategy(parameters);
+
// add seeds
elements1.push_back(elements_copy[seed1]); // MAY THROW, STRONG (copy)
elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy)
// calculate boxes
- detail::bounds(rtree::element_indexable(elements_copy[seed1], translator), box1);
- detail::bounds(rtree::element_indexable(elements_copy[seed2], translator), box2);
+ detail::bounds(rtree::element_indexable(elements_copy[seed1], translator),
+ box1, strategy);
+ detail::bounds(rtree::element_indexable(elements_copy[seed2], translator),
+ box2, strategy);
// remove seeds
if (seed1 < seed2)
@@ -185,7 +200,8 @@ struct redistribute_elements<Value, Options, Translator, Box, Allocators, quadra
content_type content_increase1 = 0;
content_type content_increase2 = 0;
el_it = pick_next(elements_copy.rbegin(), elements_copy.rend(),
- box1, box2, content1, content2, translator,
+ box1, box2, content1, content2,
+ translator, strategy,
content_increase1, content_increase2);
if ( content_increase1 < content_increase2 ||
@@ -208,13 +224,13 @@ struct redistribute_elements<Value, Options, Translator, Box, Allocators, quadra
if ( insert_into_group1 )
{
elements1.push_back(elem); // MAY THROW, STRONG (copy)
- geometry::expand(box1, indexable);
+ index::detail::expand(box1, indexable, strategy);
content1 = index::detail::content(box1);
}
else
{
elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)
- geometry::expand(box2, indexable);
+ index::detail::expand(box2, indexable, strategy);
content2 = index::detail::content(box2);
}
@@ -248,6 +264,7 @@ struct redistribute_elements<Value, Options, Translator, Box, Allocators, quadra
Box const& box1, Box const& box2,
content_type const& content1, content_type const& content2,
Translator const& translator,
+ typename index::detail::strategy_type<parameters_type>::type const& strategy,
content_type & out_content_increase1, content_type & out_content_increase2)
{
typedef typename boost::iterator_value<It>::type element_type;
@@ -266,8 +283,8 @@ struct redistribute_elements<Value, Options, Translator, Box, Allocators, quadra
// calculate enlarged boxes and areas
Box enlarged_box1(box1);
Box enlarged_box2(box2);
- geometry::expand(enlarged_box1, indexable);
- geometry::expand(enlarged_box2, indexable);
+ index::detail::expand(enlarged_box1, indexable, strategy);
+ index::detail::expand(enlarged_box2, indexable, strategy);
content_type enlarged_content1 = index::detail::content(enlarged_box1);
content_type enlarged_content2 = index::detail::content(enlarged_box2);
diff --git a/boost/geometry/index/detail/rtree/query_iterators.hpp b/boost/geometry/index/detail/rtree/query_iterators.hpp
index 83be106b8b..84a5e5df04 100644
--- a/boost/geometry/index/detail/rtree/query_iterators.hpp
+++ b/boost/geometry/index/detail/rtree/query_iterators.hpp
@@ -61,6 +61,7 @@ struct end_query_iterator
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>
class spatial_query_iterator
{
+ typedef typename Options::parameters_type parameters_type;
typedef visitors::spatial_query_incremental<Value, Options, Translator, Box, Allocators, Predicates> visitor_type;
typedef typename visitor_type::node_pointer node_pointer;
@@ -74,12 +75,12 @@ public:
inline spatial_query_iterator()
{}
- inline spatial_query_iterator(Translator const& t, Predicates const& p)
- : m_visitor(t, p)
+ inline spatial_query_iterator(parameters_type const& par, Translator const& t, Predicates const& p)
+ : m_visitor(par, t, p)
{}
- inline spatial_query_iterator(node_pointer root, Translator const& t, Predicates const& p)
- : m_visitor(t, p)
+ inline spatial_query_iterator(node_pointer root, parameters_type const& par, Translator const& t, Predicates const& p)
+ : m_visitor(par, t, p)
{
m_visitor.initialize(root);
}
@@ -129,6 +130,7 @@ private:
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates, unsigned NearestPredicateIndex>
class distance_query_iterator
{
+ typedef typename Options::parameters_type parameters_type;
typedef visitors::distance_query_incremental<Value, Options, Translator, Box, Allocators, Predicates, NearestPredicateIndex> visitor_type;
typedef typename visitor_type::node_pointer node_pointer;
@@ -142,12 +144,12 @@ public:
inline distance_query_iterator()
{}
- inline distance_query_iterator(Translator const& t, Predicates const& p)
- : m_visitor(t, p)
+ inline distance_query_iterator(parameters_type const& par, Translator const& t, Predicates const& p)
+ : m_visitor(par, t, p)
{}
- inline distance_query_iterator(node_pointer root, Translator const& t, Predicates const& p)
- : m_visitor(t, p)
+ inline distance_query_iterator(node_pointer root, parameters_type const& par, Translator const& t, Predicates const& p)
+ : m_visitor(par, t, p)
{
m_visitor.initialize(root);
}
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 2ac6eb27c9..209f6ebb20 100644
--- a/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
+++ b/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2019 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -57,11 +61,16 @@ public:
// children are leafs
if ( node_relative_level <= 1 )
{
- return choose_by_minimum_overlap_cost(children, indexable, parameters.get_overlap_cost_threshold());
+ return choose_by_minimum_overlap_cost(children, indexable,
+ parameters.get_overlap_cost_threshold(),
+ index::detail::get_strategy(parameters));
}
// children are internal nodes
else
- return choose_by_minimum_content_cost(children, indexable);
+ {
+ return choose_by_minimum_content_cost(children, indexable,
+ index::detail::get_strategy(parameters));
+ }
}
private:
@@ -79,10 +88,11 @@ private:
}
};
- template <typename Indexable>
+ template <typename Indexable, typename Strategy>
static inline size_t choose_by_minimum_overlap_cost(children_type const& children,
Indexable const& indexable,
- size_t overlap_cost_threshold)
+ size_t overlap_cost_threshold,
+ Strategy const& strategy)
{
const size_t children_count = children.size();
@@ -100,7 +110,7 @@ private:
// expanded child node's box
Box box_exp(ch_i.first);
- geometry::expand(box_exp, indexable);
+ index::detail::expand(box_exp, indexable, strategy);
// areas difference
content_type content = index::detail::content(box_exp);
@@ -131,7 +141,11 @@ private:
}
// calculate minimum or nearly minimum overlap cost
- choosen_index = choose_by_minimum_overlap_cost_first_n(children, indexable, first_n_children_count, children_count, children_contents);
+ choosen_index = choose_by_minimum_overlap_cost_first_n(children, indexable,
+ first_n_children_count,
+ children_count,
+ children_contents,
+ strategy);
}
return choosen_index;
@@ -143,12 +157,13 @@ private:
|| (p1.content_diff == p2.content_diff && (p1.content) < (p2.content));
}
- template <typename Indexable, typename ChildrenContents>
+ template <typename Indexable, typename ChildrenContents, typename Strategy>
static inline size_t choose_by_minimum_overlap_cost_first_n(children_type const& children,
Indexable const& indexable,
size_t const first_n_children_count,
size_t const children_count,
- ChildrenContents const& children_contents)
+ ChildrenContents const& children_contents,
+ Strategy const& strategy)
{
BOOST_GEOMETRY_INDEX_ASSERT(first_n_children_count <= children_count, "unexpected value");
BOOST_GEOMETRY_INDEX_ASSERT(children_contents.size() == children_count, "unexpected number of elements");
@@ -170,7 +185,7 @@ private:
Box box_exp(ch_i.first);
// calculate expanded box of child node ch_i
- geometry::expand(box_exp, indexable);
+ index::detail::expand(box_exp, indexable, strategy);
content_type overlap_diff = 0;
@@ -181,10 +196,10 @@ private:
{
child_type const& ch_j = children[j];
- content_type overlap_exp = index::detail::intersection_content(box_exp, ch_j.first);
+ content_type overlap_exp = index::detail::intersection_content(box_exp, ch_j.first, strategy);
if ( overlap_exp < -std::numeric_limits<content_type>::epsilon() || std::numeric_limits<content_type>::epsilon() < overlap_exp )
{
- overlap_diff += overlap_exp - index::detail::intersection_content(ch_i.first, ch_j.first);
+ overlap_diff += overlap_exp - index::detail::intersection_content(ch_i.first, ch_j.first, strategy);
}
}
}
@@ -205,8 +220,10 @@ private:
return choosen_index;
}
- template <typename Indexable>
- static inline size_t choose_by_minimum_content_cost(children_type const& children, Indexable const& indexable)
+ template <typename Indexable, typename Strategy>
+ static inline size_t choose_by_minimum_content_cost(children_type const& children,
+ Indexable const& indexable,
+ Strategy const& strategy)
{
size_t children_count = children.size();
@@ -222,7 +239,7 @@ private:
// expanded child node's box
Box box_exp(ch_i.first);
- geometry::expand(box_exp, indexable);
+ index::detail::expand(box_exp, indexable, strategy);
// areas difference
content_type content = index::detail::content(box_exp);
diff --git a/boost/geometry/index/detail/rtree/rstar/insert.hpp b/boost/geometry/index/detail/rtree/rstar/insert.hpp
index 0abf96ddfc..73a5ccefce 100644
--- a/boost/geometry/index/detail/rtree/rstar/insert.hpp
+++ b/boost/geometry/index/detail/rtree/rstar/insert.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -21,6 +25,37 @@ namespace detail { namespace rtree { namespace visitors {
namespace rstar {
+// Utility to distinguish between default and non-default index strategy
+template <typename Point1, typename Point2, typename Strategy>
+struct comparable_distance_point_point
+{
+ typedef typename Strategy::comparable_distance_point_point_strategy_type strategy_type;
+ typedef typename geometry::comparable_distance_result
+ <
+ Point1, Point2, strategy_type
+ >::type result_type;
+
+ static inline strategy_type get_strategy(Strategy const& strategy)
+ {
+ return strategy.get_comparable_distance_point_point_strategy();
+ }
+};
+
+template <typename Point1, typename Point2>
+struct comparable_distance_point_point<Point1, Point2, default_strategy>
+{
+ typedef default_strategy strategy_type;
+ typedef typename geometry::default_comparable_distance_result
+ <
+ Point1, Point2
+ >::type result_type;
+
+ static inline strategy_type get_strategy(default_strategy const& )
+ {
+ return strategy_type();
+ }
+};
+
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class remove_elements_to_reinsert
{
@@ -46,10 +81,13 @@ public:
typedef typename rtree::elements_type<Node>::type elements_type;
typedef typename elements_type::value_type element_type;
typedef typename geometry::point_type<Box>::type point_type;
+ typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
// TODO: awulkiew - change second point_type to the point type of the Indexable?
- typedef typename
- geometry::default_comparable_distance_result<point_type>::type
- comparable_distance_type;
+ typedef rstar::comparable_distance_point_point
+ <
+ point_type, point_type, strategy_type
+ > comparable_distance_pp;
+ typedef typename comparable_distance_pp::result_type comparable_distance_type;
elements_type & elements = rtree::elements(n);
@@ -74,13 +112,16 @@ public:
// If constructor is used instead of resize() MS implementation leaks here
sorted_elements.reserve(elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
+ typename comparable_distance_pp::strategy_type
+ cdist_strategy = comparable_distance_pp::get_strategy(index::detail::get_strategy(parameters));
+
for ( typename elements_type::const_iterator it = elements.begin() ;
it != elements.end() ; ++it )
{
point_type element_center;
geometry::centroid( rtree::element_indexable(*it, translator), element_center);
sorted_elements.push_back(std::make_pair(
- geometry::comparable_distance(node_center, element_center),
+ geometry::comparable_distance(node_center, element_center, cdist_strategy),
*it)); // MAY THROW (V, E: copy)
}
@@ -246,13 +287,17 @@ struct level_insert_base
inline void recalculate_aabb(Node const& n) const
{
base::m_traverse_data.current_element().first =
- elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator);
+ elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(),
+ base::m_translator,
+ index::detail::get_strategy(base::m_parameters));
}
inline void recalculate_aabb(leaf const& n) const
{
base::m_traverse_data.current_element().first =
- values_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator);
+ values_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(),
+ base::m_translator,
+ index::detail::get_strategy(base::m_parameters));
}
size_type result_relative_level;
diff --git a/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
index 6a9261ba5b..0b19a9e9bd 100644
--- a/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
+++ b/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -30,23 +34,27 @@ namespace detail { namespace rtree {
namespace rstar {
-template <typename Element, typename Translator, typename Tag, size_t Corner, size_t AxisIndex>
+template <typename Element, typename Parameters, typename Translator, typename Tag, size_t Corner, size_t AxisIndex>
class element_axis_corner_less
{
typedef typename rtree::element_indexable_type<Element, Translator>::type indexable_type;
typedef typename geometry::point_type<indexable_type>::type point_type;
typedef geometry::model::box<point_type> bounds_type;
- typedef index::detail::bounded_view<indexable_type, bounds_type> bounded_view_type;
+ typedef typename index::detail::strategy_type<Parameters>::type strategy_type;
+ typedef index::detail::bounded_view
+ <
+ indexable_type, bounds_type, strategy_type
+ > bounded_view_type;
public:
- element_axis_corner_less(Translator const& tr)
- : m_tr(tr)
+ element_axis_corner_less(Translator const& tr, strategy_type const& strategy)
+ : m_tr(tr), m_strategy(strategy)
{}
bool operator()(Element const& e1, Element const& e2) const
{
- bounded_view_type bounded_ind1(rtree::element_indexable(e1, m_tr));
- bounded_view_type bounded_ind2(rtree::element_indexable(e2, m_tr));
+ bounded_view_type bounded_ind1(rtree::element_indexable(e1, m_tr), m_strategy);
+ bounded_view_type bounded_ind2(rtree::element_indexable(e2, m_tr), m_strategy);
return geometry::get<Corner, AxisIndex>(bounded_ind1)
< geometry::get<Corner, AxisIndex>(bounded_ind2);
@@ -54,13 +62,16 @@ public:
private:
Translator const& m_tr;
+ strategy_type const& m_strategy;
};
-template <typename Element, typename Translator, size_t Corner, size_t AxisIndex>
-class element_axis_corner_less<Element, Translator, box_tag, Corner, AxisIndex>
+template <typename Element, typename Parameters, typename Translator, size_t Corner, size_t AxisIndex>
+class element_axis_corner_less<Element, Parameters, Translator, box_tag, Corner, AxisIndex>
{
+ typedef typename index::detail::strategy_type<Parameters>::type strategy_type;
+
public:
- element_axis_corner_less(Translator const& tr)
+ element_axis_corner_less(Translator const& tr, strategy_type const&)
: m_tr(tr)
{}
@@ -74,11 +85,13 @@ private:
Translator const& m_tr;
};
-template <typename Element, typename Translator, size_t Corner, size_t AxisIndex>
-class element_axis_corner_less<Element, Translator, point_tag, Corner, AxisIndex>
+template <typename Element, typename Parameters, typename Translator, size_t Corner, size_t AxisIndex>
+class element_axis_corner_less<Element, Parameters, Translator, point_tag, Corner, AxisIndex>
{
+ typedef typename index::detail::strategy_type<Parameters>::type strategy_type;
+
public:
- element_axis_corner_less(Translator const& tr)
+ element_axis_corner_less(Translator const& tr, strategy_type const& )
: m_tr(tr)
{}
@@ -113,6 +126,9 @@ struct choose_split_axis_and_index_for_corner
BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == parameters.get_max_elements() + 1, "wrong number of elements");
+ typename index::detail::strategy_type<Parameters>::type const&
+ strategy = index::detail::get_strategy(parameters);
+
// copy elements
Elements elements_copy(elements); // MAY THROW, STRONG (alloc, copy)
@@ -120,7 +136,10 @@ struct choose_split_axis_and_index_for_corner
size_t const index_last = parameters.get_max_elements() - parameters.get_min_elements() + 2;
// sort elements
- element_axis_corner_less<element_type, Translator, indexable_tag, Corner, AxisIndex> elements_less(translator);
+ element_axis_corner_less
+ <
+ element_type, Parameters, Translator, indexable_tag, Corner, AxisIndex
+ > elements_less(translator, strategy);
std::sort(elements_copy.begin(), elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
// {
// typename Elements::iterator f = elements_copy.begin() + index_first;
@@ -143,12 +162,14 @@ struct choose_split_axis_and_index_for_corner
// TODO - awulkiew: may be optimized - box of group 1 may be initialized with
// box of min_elems number of elements and expanded for each iteration by another element
- Box box1 = rtree::elements_box<Box>(elements_copy.begin(), elements_copy.begin() + i, translator);
- Box box2 = rtree::elements_box<Box>(elements_copy.begin() + i, elements_copy.end(), translator);
+ Box box1 = rtree::elements_box<Box>(elements_copy.begin(), elements_copy.begin() + i,
+ translator, strategy);
+ Box box2 = rtree::elements_box<Box>(elements_copy.begin() + i, elements_copy.end(),
+ translator, strategy);
sum_of_margins += index::detail::comparable_margin(box1) + index::detail::comparable_margin(box2);
- content_type ovl = index::detail::intersection_content(box1, box2);
+ content_type ovl = index::detail::intersection_content(box1, box2, strategy);
content_type con = index::detail::content(box1) + index::detail::content(box2);
// TODO - shouldn't here be < instead of <= ?
@@ -337,14 +358,15 @@ struct nth_element
BOOST_STATIC_ASSERT(0 < Dimension);
BOOST_STATIC_ASSERT(I < Dimension);
- template <typename Elements, typename Translator>
- static inline void apply(Elements & elements, const size_t axis, const size_t index, Translator const& tr)
+ template <typename Elements, typename Parameters, typename Translator>
+ static inline void apply(Elements & elements, Parameters const& parameters,
+ const size_t axis, const size_t index, Translator const& tr)
{
//BOOST_GEOMETRY_INDEX_ASSERT(axis < Dimension, "unexpected axis value");
if ( axis != I )
{
- nth_element<Corner, Dimension, I + 1>::apply(elements, axis, index, tr); // MAY THROW, BASIC (copy)
+ nth_element<Corner, Dimension, I + 1>::apply(elements, parameters, axis, index, tr); // MAY THROW, BASIC (copy)
}
else
{
@@ -352,7 +374,13 @@ struct nth_element
typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
typedef typename tag<indexable_type>::type indexable_tag;
- element_axis_corner_less<element_type, Translator, indexable_tag, Corner, I> less(tr);
+ typename index::detail::strategy_type<Parameters>::type
+ strategy = index::detail::get_strategy(parameters);
+
+ element_axis_corner_less
+ <
+ element_type, Parameters, Translator, indexable_tag, Corner, I
+ > less(tr, strategy);
index::detail::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
}
}
@@ -361,8 +389,9 @@ struct nth_element
template <size_t Corner, size_t Dimension>
struct nth_element<Corner, Dimension, Dimension>
{
- template <typename Elements, typename Translator>
- static inline void apply(Elements & /*elements*/, const size_t /*axis*/, const size_t /*index*/, Translator const& /*tr*/)
+ template <typename Elements, typename Parameters, typename Translator>
+ static inline void apply(Elements & /*elements*/, Parameters const& /*parameters*/,
+ const size_t /*axis*/, const size_t /*index*/, Translator const& /*tr*/)
{}
};
@@ -432,23 +461,28 @@ struct redistribute_elements<Value, Options, Translator, Box, Allocators, rstar_
if ( split_corner == static_cast<size_t>(min_corner) )
{
rstar::nth_element<min_corner, dimension>
- ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
+ ::apply(elements_copy, parameters, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
}
else
{
rstar::nth_element<max_corner, dimension>
- ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
+ ::apply(elements_copy, parameters, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
}
BOOST_TRY
{
+ typename index::detail::strategy_type<parameters_type>::type const&
+ strategy = index::detail::get_strategy(parameters);
+
// copy elements to nodes
elements1.assign(elements_copy.begin(), elements_copy.begin() + split_index); // MAY THROW, BASIC
elements2.assign(elements_copy.begin() + split_index, elements_copy.end()); // MAY THROW, BASIC
// calculate boxes
- box1 = rtree::elements_box<Box>(elements1.begin(), elements1.end(), translator);
- box2 = rtree::elements_box<Box>(elements2.begin(), elements2.end(), translator);
+ box1 = rtree::elements_box<Box>(elements1.begin(), elements1.end(),
+ translator, strategy);
+ box2 = rtree::elements_box<Box>(elements2.begin(), elements2.end(),
+ translator, strategy);
}
BOOST_CATCH(...)
{
diff --git a/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp b/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp
index 8e0560379b..b5fe5a0e28 100644
--- a/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp
+++ b/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -22,12 +26,14 @@ template <typename Value, typename Options, typename Translator, typename Box, t
class are_boxes_ok
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
- typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
- typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
public:
- are_boxes_ok(Translator const& tr, bool exact_match)
- : result(false), m_tr(tr), m_is_root(true), m_exact_match(exact_match)
+ are_boxes_ok(parameters_type const& parameters, Translator const& tr, bool exact_match)
+ : result(false), m_parameters(parameters), m_tr(tr), m_is_root(true), m_exact_match(exact_match)
{}
void operator()(internal_node const& n)
@@ -60,7 +66,8 @@ public:
m_box = box_bckup;
m_is_root = is_root_bckup;
- Box box_exp = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);
+ Box box_exp = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr,
+ index::detail::get_strategy(m_parameters));
if ( m_exact_match )
result = m_is_root || geometry::equals(box_exp, m_box);
@@ -82,7 +89,8 @@ public:
return;
}
- Box box_exp = rtree::values_box<Box>(elements.begin(), elements.end(), m_tr);
+ Box box_exp = rtree::values_box<Box>(elements.begin(), elements.end(), m_tr,
+ index::detail::get_strategy(m_parameters));
if ( m_exact_match )
result = geometry::equals(box_exp, m_box);
@@ -96,6 +104,7 @@ public:
bool result;
private:
+ parameters_type const& m_parameters;
Translator const& m_tr;
Box m_box;
bool m_is_root;
@@ -116,7 +125,7 @@ bool are_boxes_ok(Rtree const& tree, bool exact_match = true)
typename RTV::translator_type,
typename RTV::box_type,
typename RTV::allocators_type
- > v(rtv.translator(), exact_match);
+ > v(tree.parameters(), rtv.translator(), exact_match);
rtv.apply_visitor(v);
diff --git a/boost/geometry/index/detail/rtree/visitors/children_box.hpp b/boost/geometry/index/detail/rtree/visitors/children_box.hpp
index 6c1bafd3de..0d26a79c3e 100644
--- a/boost/geometry/index/detail/rtree/visitors/children_box.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/children_box.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -19,12 +23,14 @@ template <typename Value, typename Options, typename Translator, typename Box, t
class children_box
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
- typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
- typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
public:
- inline children_box(Box & result, Translator const& tr)
- : m_result(result), m_tr(tr)
+ inline children_box(Box & result, parameters_type const& parameters, Translator const& tr)
+ : m_result(result), m_parameters(parameters), m_tr(tr)
{}
inline void operator()(internal_node const& n)
@@ -32,7 +38,8 @@ public:
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type const& elements = rtree::elements(n);
- m_result = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);
+ m_result = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr,
+ index::detail::get_strategy(m_parameters));
}
inline void operator()(leaf const& n)
@@ -40,11 +47,13 @@ public:
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type const& elements = rtree::elements(n);
- m_result = rtree::values_box<Box>(elements.begin(), elements.end(), m_tr);
+ m_result = rtree::values_box<Box>(elements.begin(), elements.end(), m_tr,
+ index::detail::get_strategy(m_parameters));
}
private:
Box & m_result;
+ parameters_type const& m_parameters;
Translator const& m_tr;
};
diff --git a/boost/geometry/index/detail/rtree/visitors/count.hpp b/boost/geometry/index/detail/rtree/visitors/count.hpp
index 7efd5b7028..2cdbd8c0ed 100644
--- a/boost/geometry/index/detail/rtree/visitors/count.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/count.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -23,10 +27,10 @@ struct count_helper
{
return i;
}
- template <typename Translator>
- static inline bool equals(Indexable const& i, Value const& v, Translator const& tr)
+ template <typename Translator, typename Strategy>
+ static inline bool equals(Indexable const& i, Value const& v, Translator const& tr, Strategy const& s)
{
- return geometry::equals(i, tr(v));
+ return index::detail::equals<Indexable>::apply(i, tr(v), s);
}
};
@@ -38,10 +42,10 @@ struct count_helper<Value, Value>
{
return tr(v);
}
- template <typename Translator>
- static inline bool equals(Value const& v1, Value const& v2, Translator const& tr)
+ template <typename Translator, typename Strategy>
+ static inline bool equals(Value const& v1, Value const& v2, Translator const& tr, Strategy const& s)
{
- return tr.equals(v1, v2);
+ return tr.equals(v1, v2, s);
}
};
@@ -49,14 +53,16 @@ template <typename ValueOrIndexable, typename Value, typename Options, typename
struct count
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
- typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
- typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
- typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
typedef count_helper<ValueOrIndexable, Value> count_help;
- inline count(ValueOrIndexable const& vori, Translator const& t)
- : value_or_indexable(vori), tr(t), found_count(0)
+ inline count(ValueOrIndexable const& vori, parameters_type const& parameters, Translator const& t)
+ : value_or_indexable(vori), m_parameters(parameters), tr(t), found_count(0)
{}
inline void operator()(internal_node const& n)
@@ -68,10 +74,9 @@ struct count
for (typename elements_type::const_iterator it = elements.begin();
it != elements.end(); ++it)
{
- if ( geometry::covered_by(
- return_ref_or_bounds(
- count_help::indexable(value_or_indexable, tr)),
- it->first) )
+ if ( index::detail::covered_by_bounds(count_help::indexable(value_or_indexable, tr),
+ it->first,
+ index::detail::get_strategy(m_parameters)) )
{
rtree::apply_visitor(*this, *it->second);
}
@@ -88,7 +93,8 @@ struct count
it != elements.end(); ++it)
{
// if value meets predicates
- if ( count_help::equals(value_or_indexable, *it, tr) )
+ if ( count_help::equals(value_or_indexable, *it, tr,
+ index::detail::get_strategy(m_parameters)) )
{
++found_count;
}
@@ -96,6 +102,7 @@ struct count
}
ValueOrIndexable const& value_or_indexable;
+ parameters_type const& m_parameters;
Translator const& tr;
typename Allocators::size_type found_count;
};
diff --git a/boost/geometry/index/detail/rtree/visitors/distance_query.hpp b/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
index b930714433..20a954dc4e 100644
--- a/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -104,6 +108,7 @@ class distance_query
{
public:
typedef typename Options::parameters_type parameters_type;
+ typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
@@ -113,8 +118,8 @@ public:
typedef typename nearest_predicate_access::type nearest_predicate_type;
typedef typename indexable_type<Translator>::type indexable_type;
- typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;
- typedef index::detail::calculate_distance<nearest_predicate_type, Box, bounds_tag> calculate_node_distance;
+ typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, strategy_type, value_tag> calculate_value_distance;
+ typedef index::detail::calculate_distance<nearest_predicate_type, Box, strategy_type, bounds_tag> calculate_node_distance;
typedef typename calculate_value_distance::result_type value_distance_type;
typedef typename calculate_node_distance::result_type node_distance_type;
@@ -124,6 +129,7 @@ public:
: m_parameters(parameters), m_translator(translator)
, m_pred(pred)
, m_result(nearest_predicate_access::get(m_pred).count, out_it)
+ , m_strategy(index::detail::get_strategy(parameters))
{}
inline void operator()(internal_node const& n)
@@ -147,12 +153,16 @@ public:
{
// if current node meets predicates
// 0 - dummy value
- if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )
+ if ( index::detail::predicates_check
+ <
+ index::detail::bounds_tag, 0, predicates_len
+ >(m_pred, 0, it->first, m_strategy) )
{
// calculate node's distance(s) for distance predicate
node_distance_type node_distance;
// if distance isn't ok - move to the next node
- if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) )
+ if ( !calculate_node_distance::apply(predicate(), it->first,
+ m_strategy, node_distance) )
{
continue;
}
@@ -226,12 +236,16 @@ public:
it != elements.end(); ++it)
{
// if value meets predicates
- if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, *it, m_translator(*it)) )
+ if ( index::detail::predicates_check
+ <
+ index::detail::value_tag, 0, predicates_len
+ >(m_pred, *it, m_translator(*it), m_strategy) )
{
// calculate values distance for distance predicate
value_distance_type value_distance;
// if distance is ok
- if ( calculate_value_distance::apply(predicate(), m_translator(*it), value_distance) )
+ if ( calculate_value_distance::apply(predicate(), m_translator(*it),
+ m_strategy, value_distance) )
{
// store value
m_result.store(*it, value_distance);
@@ -276,6 +290,8 @@ private:
Predicates m_pred;
distance_query_result<Value, Translator, value_distance_type, OutIter> m_result;
+
+ strategy_type m_strategy;
};
template <
@@ -292,6 +308,7 @@ class distance_query_incremental
{
public:
typedef typename Options::parameters_type parameters_type;
+ typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
@@ -301,8 +318,8 @@ public:
typedef typename nearest_predicate_access::type nearest_predicate_type;
typedef typename indexable_type<Translator>::type indexable_type;
- typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;
- typedef index::detail::calculate_distance<nearest_predicate_type, Box, bounds_tag> calculate_node_distance;
+ typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, strategy_type, value_tag> calculate_value_distance;
+ typedef index::detail::calculate_distance<nearest_predicate_type, Box, strategy_type, bounds_tag> calculate_node_distance;
typedef typename calculate_value_distance::result_type value_distance_type;
typedef typename calculate_node_distance::result_type node_distance_type;
@@ -342,14 +359,15 @@ public:
// , m_pred()
, current_neighbor((std::numeric_limits<size_type>::max)())
// , next_closest_node_distance((std::numeric_limits<node_distance_type>::max)())
+// , m_strategy_type()
{}
- inline distance_query_incremental(Translator const& translator, Predicates const& pred)
+ inline distance_query_incremental(parameters_type const& params, Translator const& translator, Predicates const& pred)
: m_translator(::boost::addressof(translator))
, m_pred(pred)
, current_neighbor((std::numeric_limits<size_type>::max)())
-
, next_closest_node_distance((std::numeric_limits<node_distance_type>::max)())
+ , m_strategy(index::detail::get_strategy(params))
{
BOOST_GEOMETRY_INDEX_ASSERT(0 < max_count(), "k must be greather than 0");
}
@@ -457,12 +475,16 @@ public:
{
// if current node meets predicates
// 0 - dummy value
- if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )
+ if ( index::detail::predicates_check
+ <
+ index::detail::bounds_tag, 0, predicates_len
+ >(m_pred, 0, it->first, m_strategy) )
{
// calculate node's distance(s) for distance predicate
node_distance_type node_distance;
// if distance isn't ok - move to the next node
- if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) )
+ if ( !calculate_node_distance::apply(predicate(), it->first,
+ m_strategy, node_distance) )
{
continue;
}
@@ -502,12 +524,16 @@ public:
for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
{
// if value meets predicates
- if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, *it, (*m_translator)(*it)) )
+ if ( index::detail::predicates_check
+ <
+ index::detail::value_tag, 0, predicates_len
+ >(m_pred, *it, (*m_translator)(*it), m_strategy) )
{
// calculate values distance for distance predicate
value_distance_type value_distance;
// if distance is ok
- if ( calculate_value_distance::apply(predicate(), (*m_translator)(*it), value_distance) )
+ if ( calculate_value_distance::apply(predicate(), (*m_translator)(*it),
+ m_strategy, value_distance) )
{
// if there is not enough values or current value is closer than furthest neighbour
if ( not_enough_neighbors || value_distance < greatest_distance )
@@ -574,11 +600,13 @@ private:
const Translator * m_translator;
Predicates m_pred;
-
+
internal_stack_type internal_stack;
std::vector< std::pair<value_distance_type, const Value *> > neighbors;
size_type current_neighbor;
node_distance_type next_closest_node_distance;
+
+ strategy_type m_strategy;
};
}}} // namespace detail::rtree::visitors
diff --git a/boost/geometry/index/detail/rtree/visitors/insert.hpp b/boost/geometry/index/detail/rtree/visitors/insert.hpp
index 87d5bbbcca..3c9501f370 100644
--- a/boost/geometry/index/detail/rtree/visitors/insert.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/insert.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -16,6 +20,7 @@
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/index/detail/algorithms/bounds.hpp>
#include <boost/geometry/index/detail/algorithms/content.hpp>
namespace boost { namespace geometry { namespace index {
@@ -43,7 +48,7 @@ public:
template <typename Indexable>
static inline size_t apply(internal_node & n,
Indexable const& indexable,
- parameters_type const& /*parameters*/,
+ parameters_type const& parameters,
size_t /*node_relative_level*/)
{
children_type & children = rtree::elements(n);
@@ -65,7 +70,8 @@ public:
// expanded child node's box
Box box_exp(ch_i.first);
- geometry::expand(box_exp, indexable);
+ index::detail::expand(box_exp, indexable,
+ index::detail::get_strategy(parameters));
// areas difference
content_type content = index::detail::content(box_exp);
@@ -274,7 +280,9 @@ protected:
// NOTE: This is actually only needed because conditionally the bounding
// object may be expanded below. Otherwise the indexable could be
// directly used instead
- index::detail::bounds(rtree::element_indexable(m_element, m_translator), m_element_bounds);
+ index::detail::bounds(rtree::element_indexable(m_element, m_translator),
+ m_element_bounds,
+ index::detail::get_strategy(m_parameters));
#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON
// Enlarge it in case if it's not bounding geometry type.
@@ -300,10 +308,10 @@ protected:
apply(n, rtree::element_indexable(m_element, m_translator), m_parameters, m_leafs_level - m_traverse_data.current_level);
// expand the node to contain value
- geometry::expand(
+ index::detail::expand(
rtree::elements(n)[choosen_node_index].first,
- m_element_bounds
- /*rtree::element_indexable(m_element, m_translator)*/);
+ m_element_bounds,
+ index::detail::get_strategy(m_parameters));
// next traversing step
traverse_apply_visitor(visitor, n, choosen_node_index); // MAY THROW (V, E: alloc, copy, N:alloc)
diff --git a/boost/geometry/index/detail/rtree/visitors/remove.hpp b/boost/geometry/index/detail/rtree/visitors/remove.hpp
index 7e6162a616..1a3ccd7965 100644
--- a/boost/geometry/index/detail/rtree/visitors/remove.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/remove.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -71,9 +75,9 @@ public:
internal_size_type child_node_index = 0;
for ( ; child_node_index < children.size() ; ++child_node_index )
{
- if ( geometry::covered_by(
- return_ref_or_bounds(m_translator(m_value)),
- children[child_node_index].first) )
+ if ( index::detail::covered_by_bounds(m_translator(m_value),
+ children[child_node_index].first,
+ index::detail::get_strategy(m_parameters)) )
{
// next traversing step
traverse_apply_visitor(n, child_node_index); // MAY THROW
@@ -112,7 +116,8 @@ public:
BOOST_GEOMETRY_INDEX_ASSERT((elements.size() < m_parameters.get_min_elements()) == m_is_underflow, "unexpected state");
rtree::elements(*m_parent)[m_current_child_index].first
- = rtree::elements_box<Box>(elements.begin(), elements.end(), m_translator);
+ = rtree::elements_box<Box>(elements.begin(), elements.end(), m_translator,
+ index::detail::get_strategy(m_parameters));
}
// n is root node
else
@@ -145,11 +150,11 @@ public:
{
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type & elements = rtree::elements(n);
-
+
// find value and remove it
for ( typename elements_type::iterator it = elements.begin() ; it != elements.end() ; ++it )
{
- if ( m_translator.equals(*it, m_value) )
+ if ( m_translator.equals(*it, m_value, index::detail::get_strategy(m_parameters)) )
{
rtree::move_from_back(elements, it); // MAY THROW (V: copy)
elements.pop_back();
@@ -170,7 +175,8 @@ public:
if ( 0 != m_parent )
{
rtree::elements(*m_parent)[m_current_child_index].first
- = rtree::values_box<Box>(elements.begin(), elements.end(), m_translator);
+ = rtree::values_box<Box>(elements.begin(), elements.end(), m_translator,
+ index::detail::get_strategy(m_parameters));
}
}
}
diff --git a/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp b/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
index b9cd0ae2c0..c94248cfd0 100644
--- a/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -19,16 +23,19 @@ template <typename Value, typename Options, typename Translator, typename Box, t
struct spatial_query
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
- typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
- typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
- typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+ typedef typename Options::parameters_type parameters_type;
+ typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
typedef typename Allocators::size_type size_type;
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
- inline spatial_query(Translator const& t, Predicates const& p, OutIter out_it)
- : tr(t), pred(p), out_iter(out_it), found_count(0)
+ inline spatial_query(parameters_type const& par, Translator const& t, Predicates const& p, OutIter out_it)
+ : tr(t), pred(p), out_iter(out_it), found_count(0), strategy(index::detail::get_strategy(par))
{}
inline void operator()(internal_node const& n)
@@ -42,8 +49,13 @@ struct spatial_query
{
// if node meets predicates
// 0 - dummy value
- if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(pred, 0, it->first) )
+ if ( index::detail::predicates_check
+ <
+ index::detail::bounds_tag, 0, predicates_len
+ >(pred, 0, it->first, strategy) )
+ {
rtree::apply_visitor(*this, *it->second);
+ }
}
}
@@ -57,7 +69,10 @@ struct spatial_query
it != elements.end(); ++it)
{
// if value meets predicates
- if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(pred, *it, tr(*it)) )
+ if ( index::detail::predicates_check
+ <
+ index::detail::value_tag, 0, predicates_len
+ >(pred, *it, tr(*it), strategy) )
{
*out_iter = *it;
++out_iter;
@@ -73,12 +88,17 @@ struct spatial_query
OutIter out_iter;
size_type found_count;
+
+ strategy_type strategy;
};
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>
class spatial_query_incremental
: public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
+ typedef typename Options::parameters_type parameters_type;
+ typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
+
public:
typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
@@ -99,13 +119,15 @@ public:
// , m_pred()
, m_values(NULL)
, m_current()
+// , m_strategy()
{}
- inline spatial_query_incremental(Translator const& t, Predicates const& p)
+ inline spatial_query_incremental(parameters_type const& params, Translator const& t, Predicates const& p)
: m_translator(::boost::addressof(t))
, m_pred(p)
, m_values(NULL)
, m_current()
+ , m_strategy(index::detail::get_strategy(params))
{}
inline void operator()(internal_node const& n)
@@ -151,8 +173,13 @@ public:
{
// return if next value is found
Value const& v = *m_current;
- if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, v, (*m_translator)(v)) )
+ if (index::detail::predicates_check
+ <
+ index::detail::value_tag, 0, predicates_len
+ >(m_pred, v, (*m_translator)(v), m_strategy))
+ {
return;
+ }
++m_current;
}
@@ -180,8 +207,13 @@ public:
++m_internal_stack.back().first;
// next node is found, push it to the stack
- if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )
+ if (index::detail::predicates_check
+ <
+ index::detail::bounds_tag, 0, predicates_len
+ >(m_pred, 0, it->first, m_strategy))
+ {
rtree::apply_visitor(*this, *(it->second));
+ }
}
}
}
@@ -205,6 +237,8 @@ private:
std::vector< std::pair<internal_iterator, internal_iterator> > m_internal_stack;
const leaf_elements * m_values;
leaf_iterator m_current;
+
+ strategy_type m_strategy;
};
}}} // namespace detail::rtree::visitors
diff --git a/boost/geometry/index/detail/translator.hpp b/boost/geometry/index/detail/translator.hpp
index f377c720aa..dd49b61fe5 100644
--- a/boost/geometry/index/detail/translator.hpp
+++ b/boost/geometry/index/detail/translator.hpp
@@ -2,6 +2,10 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -13,6 +17,30 @@ namespace boost { namespace geometry { namespace index {
namespace detail {
+template <typename Strategy>
+struct translator_equals
+{
+ template <typename EqualTo, typename Value>
+ static inline bool apply(EqualTo const& equal_to,
+ Value const& v1, Value const& v2,
+ Strategy const& strategy)
+ {
+ return equal_to(v1, v2, strategy);
+ }
+};
+
+template <>
+struct translator_equals<default_strategy>
+{
+ template <typename EqualTo, typename Value>
+ static inline bool apply(EqualTo const& equal_to,
+ Value const& v1, Value const& v2,
+ default_strategy const&)
+ {
+ return equal_to(v1, v2);
+ }
+};
+
template <typename IndexableGetter, typename EqualTo>
struct translator
: public IndexableGetter
@@ -30,11 +58,14 @@ struct translator
return IndexableGetter::operator()(value);
}
- template <typename Value>
- bool equals(Value const& v1, Value const& v2) const
- {
- return EqualTo::operator()(v1, v2);
- }
+ template <typename Value, typename Strategy>
+ bool equals(Value const& v1, Value const& v2, Strategy const& strategy) const
+ {
+ return translator_equals
+ <
+ Strategy
+ >::apply(static_cast<EqualTo const&>(*this), v1, v2, strategy);
+ }
};
template <typename IndexableGetter>
diff --git a/boost/geometry/index/equal_to.hpp b/boost/geometry/index/equal_to.hpp
index 2fb1ed216c..f457f51847 100644
--- a/boost/geometry/index/equal_to.hpp
+++ b/boost/geometry/index/equal_to.hpp
@@ -2,6 +2,10 @@
//
// Copyright (c) 2011-2016 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -12,22 +16,73 @@
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
#include <boost/geometry/index/indexable.hpp>
-namespace boost { namespace geometry { namespace index { namespace detail {
+namespace boost { namespace geometry { namespace index { namespace detail
+{
template <typename Geometry,
typename Tag = typename geometry::tag<Geometry>::type>
struct equals
{
- inline static bool apply(Geometry const& g1, Geometry const& g2)
+ template <typename Strategy>
+ inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const&)
+ {
+ return geometry::equals(g1, g2);
+ }
+};
+
+template <typename Geometry>
+struct equals<Geometry, point_tag>
+{
+ inline static bool apply(Geometry const& g1, Geometry const& g2, default_strategy const&)
{
return geometry::equals(g1, g2);
}
+
+ template <typename Strategy>
+ inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const&)
+ {
+ return geometry::equals(g1, g2, typename Strategy::within_point_point_strategy_type());
+ }
};
+template <typename Geometry>
+struct equals<Geometry, box_tag>
+{
+ inline static bool apply(Geometry const& g1, Geometry const& g2, default_strategy const&)
+ {
+ return geometry::equals(g1, g2);
+ }
+
+ template <typename Strategy>
+ inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const&)
+ {
+ // NOTE: there is no strategy for equals(box, box) so pass dummy variable
+ // TODO: there should be a strategy even if it is the same for all CSes in case undefined_cs was used
+ return geometry::equals(g1, g2, 0);
+ }
+};
+
+template <typename Geometry>
+struct equals<Geometry, segment_tag>
+{
+ inline static bool apply(Geometry const& g1, Geometry const& g2, default_strategy const&)
+ {
+ return geometry::equals(g1, g2);
+ }
+
+ template <typename Strategy>
+ inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const& s)
+ {
+ return geometry::equals(g1, g2, s.get_relate_segment_segment_strategy());
+ }
+};
+
+
template <typename Geometry, typename Tag>
struct equals<Geometry *, Tag>
{
- inline static bool apply(const Geometry * g1, const Geometry * g2)
+ template <typename Strategy>
+ inline static bool apply(const Geometry * g1, const Geometry * g2, Strategy const&)
{
return g1 == g2;
}
@@ -36,7 +91,8 @@ struct equals<Geometry *, Tag>
template <typename T>
struct equals<T, void>
{
- inline static bool apply(T const& v1, T const& v2)
+ template <typename Strategy>
+ inline static bool apply(T const& v1, T const& v2, Strategy const&)
{
return v1 == v2;
}
@@ -45,7 +101,8 @@ struct equals<T, void>
template <typename T>
struct equals<T *, void>
{
- inline static bool apply(const T * v1, const T * v2)
+ template <typename Strategy>
+ inline static bool apply(const T * v1, const T * v2, Strategy const&)
{
return v1 == v2;
}
@@ -54,19 +111,21 @@ struct equals<T *, void>
template <typename Tuple, size_t I, size_t N>
struct tuple_equals
{
- inline static bool apply(Tuple const& t1, Tuple const& t2)
+ template <typename Strategy>
+ inline static bool apply(Tuple const& t1, Tuple const& t2, Strategy const& strategy)
{
typedef typename boost::tuples::element<I, Tuple>::type T;
- return equals<T>::apply(boost::get<I>(t1), boost::get<I>(t2))
- && tuple_equals<Tuple, I+1, N>::apply(t1, t2);
+ return equals<T>::apply(boost::get<I>(t1), boost::get<I>(t2), strategy)
+ && tuple_equals<Tuple, I + 1, N>::apply(t1, t2, strategy);
}
};
template <typename Tuple, size_t I>
struct tuple_equals<Tuple, I, I>
{
- inline static bool apply(Tuple const&, Tuple const&)
+ template <typename Strategy>
+ inline static bool apply(Tuple const&, Tuple const&, Strategy const&)
{
return true;
}
@@ -102,9 +161,10 @@ struct equal_to
\param r Second value.
\return true if values are equal.
*/
- inline bool operator()(Value const& l, Value const& r) const
+ template <typename Strategy>
+ inline bool operator()(Value const& l, Value const& r, Strategy const& strategy) const
{
- return detail::equals<Value>::apply(l ,r);
+ return detail::equals<Value>::apply(l, r, strategy);
}
};
@@ -130,10 +190,12 @@ struct equal_to<std::pair<T1, T2>, false>
\param r Second value.
\return true if values are equal.
*/
- inline bool operator()(std::pair<T1, T2> const& l, std::pair<T1, T2> const& r) const
+ template <typename Strategy>
+ inline bool operator()(std::pair<T1, T2> const& l, std::pair<T1, T2> const& r,
+ Strategy const& strategy) const
{
- return detail::equals<T1>::apply(l.first, r.first)
- && detail::equals<T2>::apply(l.second, r.second);
+ return detail::equals<T1>::apply(l.first, r.first, strategy)
+ && detail::equals<T2>::apply(l.second, r.second, strategy);
}
};
@@ -159,11 +221,13 @@ struct equal_to<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, false>
\param r Second value.
\return true if values are equal.
*/
- inline bool operator()(value_type const& l, value_type const& r) const
+ template <typename Strategy>
+ inline bool operator()(value_type const& l, value_type const& r,
+ Strategy const& strategy) const
{
return detail::tuple_equals<
value_type, 0, boost::tuples::length<value_type>::value
- >::apply(l ,r);
+ >::apply(l, r, strategy);
}
};
@@ -178,19 +242,21 @@ namespace boost { namespace geometry { namespace index { namespace detail {
template <typename Tuple, size_t I, size_t N>
struct std_tuple_equals
{
- inline static bool apply(Tuple const& t1, Tuple const& t2)
+ template <typename Strategy>
+ inline static bool apply(Tuple const& t1, Tuple const& t2, Strategy const& strategy)
{
typedef typename std::tuple_element<I, Tuple>::type T;
- return equals<T>::apply(std::get<I>(t1), std::get<I>(t2))
- && std_tuple_equals<Tuple, I+1, N>::apply(t1, t2);
+ return equals<T>::apply(std::get<I>(t1), std::get<I>(t2), strategy)
+ && std_tuple_equals<Tuple, I + 1, N>::apply(t1, t2, strategy);
}
};
template <typename Tuple, size_t I>
struct std_tuple_equals<Tuple, I, I>
{
- inline static bool apply(Tuple const&, Tuple const&)
+ template <typename Strategy>
+ inline static bool apply(Tuple const&, Tuple const&, Strategy const&)
{
return true;
}
@@ -218,11 +284,12 @@ struct equal_to<std::tuple<Args...>, false>
\param r Second value.
\return true if values are equal.
*/
- bool operator()(value_type const& l, value_type const& r) const
+ template <typename Strategy>
+ bool operator()(value_type const& l, value_type const& r, Strategy const& strategy) const
{
return detail::std_tuple_equals<
value_type, 0, std::tuple_size<value_type>::value
- >::apply(l ,r);
+ >::apply(l, r, strategy);
}
};
@@ -258,7 +325,13 @@ struct equal_to
*/
inline bool operator()(Value const& l, Value const& r) const
{
- return detail::equal_to<Value>::operator()(l ,r);
+ return detail::equal_to<Value>::operator()(l, r, default_strategy());
+ }
+
+ template <typename Strategy>
+ inline bool operator()(Value const& l, Value const& r, Strategy const& strategy) const
+ {
+ return detail::equal_to<Value>::operator()(l, r, strategy);
}
};
diff --git a/boost/geometry/index/parameters.hpp b/boost/geometry/index/parameters.hpp
index 1a9469c103..7c5b3fb4fc 100644
--- a/boost/geometry/index/parameters.hpp
+++ b/boost/geometry/index/parameters.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -253,6 +257,78 @@ private:
size_t m_overlap_cost_threshold;
};
+
+template <typename Parameters, typename Strategy>
+class parameters
+ : public Parameters
+ , private Strategy
+{
+public:
+ parameters()
+ : Parameters(), Strategy()
+ {}
+
+ parameters(Parameters const& params)
+ : Parameters(params), Strategy()
+ {}
+
+ parameters(Parameters const& params, Strategy const& strategy)
+ : Parameters(params), Strategy(strategy)
+ {}
+
+ Strategy const& strategy() const
+ {
+ return static_cast<Strategy const&>(*this);
+ }
+};
+
+
+namespace detail
+{
+
+template <typename Parameters>
+struct strategy_type
+{
+ typedef default_strategy type;
+ typedef default_strategy result_type;
+};
+
+template <typename Parameters, typename Strategy>
+struct strategy_type< parameters<Parameters, Strategy> >
+{
+ typedef Strategy type;
+ typedef Strategy const& result_type;
+};
+
+
+template <typename Parameters>
+struct get_strategy_impl
+{
+ static inline default_strategy apply(Parameters const&)
+ {
+ return default_strategy();
+ }
+};
+
+template <typename Parameters, typename Strategy>
+struct get_strategy_impl<parameters<Parameters, Strategy> >
+{
+ static inline Strategy const& apply(parameters<Parameters, Strategy> const& parameters)
+ {
+ return parameters.strategy();
+ }
+};
+
+template <typename Parameters>
+inline typename strategy_type<Parameters>::result_type
+ get_strategy(Parameters const& parameters)
+{
+ return get_strategy_impl<Parameters>::apply(parameters);
+}
+
+} // namespace detail
+
+
}}} // namespace boost::geometry::index
#endif // BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
diff --git a/boost/geometry/index/rtree.hpp b/boost/geometry/index/rtree.hpp
index 1a8be031dc..ab770fd6ae 100644
--- a/boost/geometry/index/rtree.hpp
+++ b/boost/geometry/index/rtree.hpp
@@ -5,6 +5,10 @@
// Copyright (c) 2008 Federico J. Fernandez.
// Copyright (c) 2011-2019 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2019.
+// Modifications copyright (c) 2019 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)
@@ -191,15 +195,46 @@ private:
typedef bounds_type box_type;
typedef typename detail::rtree::options_type<Parameters>::type options_type;
typedef typename options_type::node_tag node_tag;
- typedef detail::rtree::allocators<allocator_type, value_type, typename options_type::parameters_type, box_type, node_tag> allocators_type;
+ typedef detail::rtree::allocators
+ <
+ allocator_type,
+ value_type,
+ typename options_type::parameters_type,
+ box_type,
+ node_tag
+ > allocators_type;
- typedef typename detail::rtree::node<value_type, typename options_type::parameters_type, box_type, allocators_type, node_tag>::type node;
- typedef typename detail::rtree::internal_node<value_type, typename options_type::parameters_type, box_type, allocators_type, node_tag>::type internal_node;
- typedef typename detail::rtree::leaf<value_type, typename options_type::parameters_type, box_type, allocators_type, node_tag>::type leaf;
+ typedef typename detail::rtree::node
+ <
+ value_type,
+ typename options_type::parameters_type,
+ box_type,
+ allocators_type,
+ node_tag
+ >::type node;
+ typedef typename detail::rtree::internal_node
+ <
+ value_type,
+ typename options_type::parameters_type,
+ box_type,
+ allocators_type,
+ node_tag
+ >::type internal_node;
+ typedef typename detail::rtree::leaf
+ <
+ value_type,
+ typename options_type::parameters_type,
+ box_type,
+ allocators_type,
+ node_tag
+ >::type leaf;
typedef typename allocators_type::node_pointer node_pointer;
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
- typedef detail::rtree::subtree_destroyer<value_type, options_type, translator_type, box_type, allocators_type> subtree_destroyer;
+ typedef detail::rtree::subtree_destroyer
+ <
+ value_type, options_type, translator_type, box_type, allocators_type
+ > subtree_destroyer;
friend class detail::rtree::utilities::view<rtree>;
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
@@ -1009,9 +1044,9 @@ private:
>::type iterator_type;
if ( !m_members.root )
- return iterator_type(m_members.translator(), predicates);
+ return iterator_type(m_members.parameters(), m_members.translator(), predicates);
- return iterator_type(m_members.root, m_members.translator(), predicates);
+ return iterator_type(m_members.root, m_members.parameters(), m_members.translator(), predicates);
}
/*!
@@ -1069,7 +1104,7 @@ private:
>
>::type iterator_type;
- return iterator_type(m_members.translator(), predicates);
+ return iterator_type(m_members.parameters(), m_members.translator(), predicates);
}
/*!
@@ -1268,8 +1303,10 @@ public:
if ( m_members.root )
{
- detail::rtree::visitors::children_box<value_type, options_type, translator_type, box_type, allocators_type>
- box_v(result, m_members.translator());
+ detail::rtree::visitors::children_box
+ <
+ value_type, options_type, translator_type, box_type, allocators_type
+ > box_v(result, m_members.parameters(), m_members.translator());
detail::rtree::apply_visitor(box_v, *m_members.root);
}
@@ -1643,8 +1680,10 @@ private:
template <typename Predicates, typename OutIter>
size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_<false> const& /*is_distance_predicate*/) const
{
- detail::rtree::visitors::spatial_query<value_type, options_type, translator_type, box_type, allocators_type, Predicates, OutIter>
- find_v(m_members.translator(), predicates, out_it);
+ detail::rtree::visitors::spatial_query
+ <
+ value_type, options_type, translator_type, box_type, allocators_type, Predicates, OutIter
+ >find_v(m_members.parameters(), m_members.translator(), predicates, out_it);
detail::rtree::apply_visitor(find_v, *m_members.root);
@@ -1698,7 +1737,7 @@ private:
translator_type,
box_type,
allocators_type
- > count_v(vori, m_members.translator());
+ > count_v(vori, m_members.parameters(), m_members.translator());
detail::rtree::apply_visitor(count_v, *m_members.root);
diff --git a/boost/geometry/io/wkt/write.hpp b/boost/geometry/io/wkt/write.hpp
index 62d1d6cb44..3daecadb43 100644
--- a/boost/geometry/io/wkt/write.hpp
+++ b/boost/geometry/io/wkt/write.hpp
@@ -5,10 +5,11 @@
// Copyright (c) 2009-2017 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2015, 2018.
-// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2018, 2019.
+// Modifications copyright (c) 2015-2019, 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.
@@ -45,6 +46,8 @@
#include <boost/geometry/io/wkt/detail/prefix.hpp>
+#include <boost/geometry/util/condition.hpp>
+
namespace boost { namespace geometry
{
@@ -159,7 +162,7 @@ struct wkt_range
}
// optionally, close range to ring by repeating the first point
- if (ForceClosurePossible
+ if (BOOST_GEOMETRY_CONDITION(ForceClosurePossible)
&& force_closure
&& boost::size(range) > 1
&& wkt_range::disjoint(*begin, *(end - 1)))
diff --git a/boost/geometry/policies/compare.hpp b/boost/geometry/policies/compare.hpp
index 7f32b7ab30..6a081af837 100644
--- a/boost/geometry/policies/compare.hpp
+++ b/boost/geometry/policies/compare.hpp
@@ -2,8 +2,8 @@
// 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.
+// This file was modified by Oracle on 2017, 2019.
+// Modifications copyright (c) 2017, 2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -39,7 +39,8 @@ namespace boost { namespace geometry
template
<
typename Point = void,
- int Dimension = -1
+ int Dimension = -1,
+ typename CSTag = void
>
struct less
{
@@ -53,6 +54,47 @@ struct less
<
strategy::compare::less,
Point, Point,
+ Dimension,
+ CSTag, CSTag
+ >::type strategy_type;
+
+ return strategy_type::apply(left, right);
+ }
+};
+
+template <int Dimension, typename CSTag>
+struct less<void, Dimension, CSTag>
+{
+ typedef bool result_type;
+
+ template <typename Point1, typename Point2>
+ inline bool operator()(Point1 const& left, Point2 const& right) const
+ {
+ typedef typename strategy::compare::services::default_strategy
+ <
+ strategy::compare::less,
+ Point1, Point2,
+ Dimension,
+ CSTag, CSTag
+ >::type strategy_type;
+
+ return strategy_type::apply(left, right);
+ }
+};
+
+template <typename Point, int Dimension>
+struct less<Point, Dimension, void>
+{
+ typedef Point first_argument_type;
+ typedef Point second_argument_type;
+ typedef bool result_type;
+
+ inline bool operator()(Point const& left, Point const& right) const
+ {
+ typedef typename strategy::compare::services::default_strategy
+ <
+ strategy::compare::less,
+ Point, Point,
Dimension
>::type strategy_type;
@@ -61,8 +103,10 @@ struct less
};
template <int Dimension>
-struct less<void, Dimension>
+struct less<void, Dimension, void>
{
+ typedef bool result_type;
+
template <typename Point1, typename Point2>
inline bool operator()(Point1 const& left, Point2 const& right) const
{
@@ -87,7 +131,8 @@ struct less<void, Dimension>
template
<
typename Point = void,
- int Dimension = -1
+ int Dimension = -1,
+ typename CSTag = void
>
struct greater
{
@@ -101,6 +146,47 @@ struct greater
<
strategy::compare::greater,
Point, Point,
+ Dimension,
+ CSTag, CSTag
+ >::type strategy_type;
+
+ return strategy_type::apply(left, right);
+ }
+};
+
+template <int Dimension, typename CSTag>
+struct greater<void, Dimension, CSTag>
+{
+ typedef bool result_type;
+
+ template <typename Point1, typename Point2>
+ bool operator()(Point1 const& left, Point2 const& right) const
+ {
+ typedef typename strategy::compare::services::default_strategy
+ <
+ strategy::compare::greater,
+ Point1, Point2,
+ Dimension,
+ CSTag, CSTag
+ >::type strategy_type;
+
+ return strategy_type::apply(left, right);
+ }
+};
+
+template <typename Point, int Dimension>
+struct greater<Point, Dimension, void>
+{
+ typedef Point first_argument_type;
+ typedef Point second_argument_type;
+ typedef bool result_type;
+
+ bool operator()(Point const& left, Point const& right) const
+ {
+ typedef typename strategy::compare::services::default_strategy
+ <
+ strategy::compare::greater,
+ Point, Point,
Dimension
>::type strategy_type;
@@ -109,8 +195,10 @@ struct greater
};
template <int Dimension>
-struct greater<void, Dimension>
+struct greater<void, Dimension, void>
{
+ typedef bool result_type;
+
template <typename Point1, typename Point2>
bool operator()(Point1 const& left, Point2 const& right) const
{
@@ -137,7 +225,8 @@ struct greater<void, Dimension>
template
<
typename Point,
- int Dimension = -1
+ int Dimension = -1,
+ typename CSTag = void
>
struct equal_to
{
@@ -151,6 +240,47 @@ struct equal_to
<
strategy::compare::equal_to,
Point, Point,
+ Dimension,
+ CSTag, CSTag
+ >::type strategy_type;
+
+ return strategy_type::apply(left, right);
+ }
+};
+
+template <int Dimension, typename CSTag>
+struct equal_to<void, Dimension, CSTag>
+{
+ typedef bool result_type;
+
+ template <typename Point1, typename Point2>
+ bool operator()(Point1 const& left, Point2 const& right) const
+ {
+ typedef typename strategy::compare::services::default_strategy
+ <
+ strategy::compare::equal_to,
+ Point1, Point2,
+ Dimension,
+ CSTag, CSTag
+ >::type strategy_type;
+
+ return strategy_type::apply(left, right);
+ }
+};
+
+template <typename Point, int Dimension>
+struct equal_to<Point, Dimension, void>
+{
+ typedef Point first_argument_type;
+ typedef Point second_argument_type;
+ typedef bool result_type;
+
+ bool operator()(Point const& left, Point const& right) const
+ {
+ typedef typename strategy::compare::services::default_strategy
+ <
+ strategy::compare::equal_to,
+ Point, Point,
Dimension
>::type strategy_type;
@@ -159,8 +289,10 @@ struct equal_to
};
template <int Dimension>
-struct equal_to<void, Dimension>
+struct equal_to<void, Dimension, void>
{
+ typedef bool result_type;
+
template <typename Point1, typename Point2>
bool operator()(Point1 const& left, Point2 const& right) const
{
diff --git a/boost/geometry/policies/robustness/get_rescale_policy.hpp b/boost/geometry/policies/robustness/get_rescale_policy.hpp
index 9bb3f885a7..4fa04fe411 100644
--- a/boost/geometry/policies/robustness/get_rescale_policy.hpp
+++ b/boost/geometry/policies/robustness/get_rescale_policy.hpp
@@ -5,10 +5,11 @@
// Copyright (c) 2014-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-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, 2019.
+// Modifications copyright (c) 2015, 2019, 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
@@ -91,29 +92,45 @@ inline void scale_box_to_integer_range(Box const& box,
assign_values(min_robust_point, min_coordinate, min_coordinate);
}
-template <typename Point, typename RobustPoint, typename Geometry, typename Factor>
+template
+<
+ typename Point, typename RobustPoint, typename Geometry,
+ typename Factor, typename EnvelopeStrategy
+>
static inline void init_rescale_policy(Geometry const& geometry,
Point& min_point,
RobustPoint& min_robust_point,
- Factor& factor)
+ Factor& factor,
+ EnvelopeStrategy const& strategy)
{
if (geometry::is_empty(geometry))
{
return;
}
- // Get bounding boxes
- model::box<Point> env = geometry::return_envelope<model::box<Point> >(geometry);
+ // Get bounding box
+ model::box<Point> env = geometry::return_envelope
+ <
+ model::box<Point>
+ >(geometry, strategy);
scale_box_to_integer_range(env, min_point, min_robust_point, factor);
}
-template <typename Point, typename RobustPoint, typename Geometry1, typename Geometry2, typename Factor>
+// NOTE: Actually it should take 2 separate strategies, one for each geometry
+// in case one of them was e.g. a Box
+template
+<
+ typename Point, typename RobustPoint, typename Geometry1, typename Geometry2,
+ typename Factor, typename EnvelopeStrategy1, typename EnvelopeStrategy2
+>
static inline void init_rescale_policy(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Point& min_point,
RobustPoint& min_robust_point,
- Factor& factor)
+ Factor& factor,
+ EnvelopeStrategy1 const& strategy1,
+ EnvelopeStrategy2 const& strategy2)
{
// Get bounding boxes (when at least one of the geometries is not empty)
bool const is_empty1 = geometry::is_empty(geometry1);
@@ -126,11 +143,11 @@ static inline void init_rescale_policy(Geometry1 const& geometry1,
model::box<Point> env;
if (is_empty1)
{
- geometry::envelope(geometry2, env);
+ geometry::envelope(geometry2, env, strategy2);
}
else if (is_empty2)
{
- geometry::envelope(geometry1, env);
+ geometry::envelope(geometry1, env, strategy1);
}
else
{
@@ -138,12 +155,12 @@ static inline void init_rescale_policy(Geometry1 const& geometry1,
// optimal MBR when then two geometries are in the spherical
// equatorial or geographic coordinate systems.
// TODO: implement envelope for two (or possibly more geometries)
- geometry::envelope(geometry1, env);
+ geometry::envelope(geometry1, env, strategy1);
model::box<Point> env2 = geometry::return_envelope
<
model::box<Point>
- >(geometry2);
- geometry::expand(env, env2);
+ >(geometry2, strategy2);
+ geometry::expand(env, env2, strategy1.get_box_expand_strategy());
}
scale_box_to_integer_range(env, min_point, min_robust_point, factor);
@@ -181,8 +198,9 @@ struct rescale_policy_type<Point, true>
template <typename Policy>
struct get_rescale_policy
{
- template <typename Geometry>
- static inline Policy apply(Geometry const& geometry)
+ template <typename Geometry, typename EnvelopeStrategy>
+ static inline Policy apply(Geometry const& geometry,
+ EnvelopeStrategy const& strategy)
{
typedef typename point_type<Geometry>::type point_type;
typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;
@@ -197,13 +215,16 @@ struct get_rescale_policy
point_type min_point;
robust_point_type min_robust_point;
factor_type factor;
- init_rescale_policy(geometry, min_point, min_robust_point, factor);
+ init_rescale_policy(geometry, min_point, min_robust_point,
+ factor, strategy);
return Policy(min_point, min_robust_point, factor);
}
- template <typename Geometry1, typename Geometry2>
- static inline Policy apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Geometry1, typename Geometry2, typename EnvelopeStrategy1, typename EnvelopeStrategy2>
+ static inline Policy apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ EnvelopeStrategy1 const& strategy1,
+ EnvelopeStrategy2 const& strategy2)
{
typedef typename point_type<Geometry1>::type point_type;
typedef typename geometry::coordinate_type<Geometry1>::type coordinate_type;
@@ -218,7 +239,8 @@ struct get_rescale_policy
point_type min_point;
robust_point_type min_robust_point;
factor_type factor;
- init_rescale_policy(geometry1, geometry2, min_point, min_robust_point, factor);
+ init_rescale_policy(geometry1, geometry2, min_point, min_robust_point,
+ factor, strategy1, strategy2);
return Policy(min_point, min_robust_point, factor);
}
@@ -228,14 +250,15 @@ struct get_rescale_policy
template <>
struct get_rescale_policy<no_rescale_policy>
{
- template <typename Geometry>
- static inline no_rescale_policy apply(Geometry const& )
+ template <typename Geometry, typename EnvelopeStrategy>
+ static inline no_rescale_policy apply(Geometry const& , EnvelopeStrategy const&)
{
return no_rescale_policy();
}
- template <typename Geometry1, typename Geometry2>
- static inline no_rescale_policy apply(Geometry1 const& , Geometry2 const& )
+ template <typename Geometry1, typename Geometry2, typename EnvelopeStrategy1, typename EnvelopeStrategy2>
+ static inline no_rescale_policy apply(Geometry1 const& , Geometry2 const& ,
+ EnvelopeStrategy1 const& , EnvelopeStrategy2 const& )
{
return no_rescale_policy();
}
@@ -245,7 +268,11 @@ struct get_rescale_policy<no_rescale_policy>
}} // namespace detail::get_rescale_policy
#endif // DOXYGEN_NO_DETAIL
-template<typename Point>
+template
+<
+ typename Point,
+ typename CSTag = typename geometry::cs_tag<Point>::type
+>
struct rescale_policy_type
: public detail::get_rescale_policy::rescale_policy_type
<
@@ -258,8 +285,8 @@ struct rescale_policy_type
&&
boost::is_same
<
- typename geometry::coordinate_system<Point>::type,
- geometry::cs::cartesian
+ CSTag,
+ geometry::cartesian_tag
>::value
#else
false
@@ -283,6 +310,7 @@ template
<
typename Geometry1,
typename Geometry2,
+ typename CSTag = typename geometry::cs_tag<Geometry1>::type,
typename Tag1 = typename tag_cast
<
typename tag<Geometry1>::type,
@@ -313,26 +341,189 @@ struct rescale_overlay_policy_type
template
<
typename Geometry1,
- typename Geometry2
+ typename Geometry2,
+ typename CSTag
>
-struct rescale_overlay_policy_type<Geometry1, Geometry2, areal_tag, areal_tag>
+struct rescale_overlay_policy_type<Geometry1, Geometry2, CSTag, areal_tag, areal_tag>
: public rescale_policy_type
<
- typename geometry::point_type<Geometry1>::type
+ typename geometry::point_type<Geometry1>::type,
+ CSTag
>
{};
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace get_rescale_policy
+{
+
+
+// get envelope strategy compatible with relate strategy based on geometry tag
+// and strategy cs_tag
+template
+<
+ typename Geometry,
+ typename Strategy,
+ typename Tag = typename geometry::tag<Geometry>::type,
+ typename CSTag = typename Strategy::cs_tag
+>
+struct get_envelope_strategy
+{
+ typedef typename Strategy::envelope_strategy_type type;
+
+ static inline type apply(Strategy const& strategy)
+ {
+ return strategy.get_envelope_strategy();
+ }
+};
+
+template <typename Geometry, typename Strategy, typename CSTag>
+struct get_envelope_strategy<Geometry, Strategy, box_tag, CSTag>
+{
+ typedef typename Strategy::envelope_box_strategy_type type;
+
+ static inline type apply(Strategy const& )
+ {
+ return type();
+ }
+};
+
+// NOTE: within::xxx_point_point shouldn't have a getter for envelope strategy
+// so dispatch by CStag. In the future strategies should probably be redesigned.
+template <typename Geometry, typename Strategy>
+struct get_envelope_strategy<Geometry, Strategy, point_tag, cartesian_tag>
+{
+ typedef strategy::envelope::cartesian_point type;
+
+ static inline type apply(Strategy const& )
+ {
+ return type();
+ }
+};
+template <typename Geometry, typename Strategy>
+struct get_envelope_strategy<Geometry, Strategy, point_tag, spherical_tag>
+{
+ typedef strategy::envelope::spherical_point type;
+
+ static inline type apply(Strategy const& )
+ {
+ return type();
+ }
+};
+
+template <typename Geometry, typename Strategy>
+struct get_envelope_strategy<Geometry, Strategy, multi_point_tag, cartesian_tag>
+{
+ typedef strategy::envelope::cartesian_point type;
+
+ static inline type apply(Strategy const& )
+ {
+ return type();
+ }
+};
+template <typename Geometry, typename Strategy>
+struct get_envelope_strategy<Geometry, Strategy, multi_point_tag, spherical_tag>
+{
+ typedef strategy::envelope::spherical_point type;
+
+ static inline type apply(Strategy const& )
+ {
+ return type();
+ }
+};
+
+
+// utility for backward-compatibility either treating the argument as geometry
+// or envelope strategy for get_rescale_policy
+template
+<
+ typename Geometry2OrStrategy,
+ typename Tag = typename geometry::tag<Geometry2OrStrategy>::type
+>
+struct get_rescale_policy_geometry_or_strategy
+{
+ template <typename Policy, typename Geometry>
+ static inline Policy apply(Geometry const& geometry, Geometry2OrStrategy const& geometry2)
+ {
+ typename geometry::strategy::envelope::services::default_strategy
+ <
+ typename geometry::tag<Geometry>::type,
+ typename geometry::cs_tag<Geometry>::type
+ >::type strategy1;
+ typename geometry::strategy::envelope::services::default_strategy
+ <
+ typename geometry::tag<Geometry2OrStrategy>::type,
+ typename geometry::cs_tag<Geometry2OrStrategy>::type
+ >::type strategy2;
+
+ return detail::get_rescale_policy::get_rescale_policy
+ <
+ Policy
+ >::apply(geometry, geometry2, strategy1, strategy2);
+ }
+};
+
+template <typename Strategy>
+struct get_rescale_policy_geometry_or_strategy<Strategy, void>
+{
+ template <typename Policy, typename Geometry>
+ static inline Policy apply(Geometry const& geometry, Strategy const& strategy)
+ {
+ return detail::get_rescale_policy::get_rescale_policy
+ <
+ Policy
+ >::apply(geometry,
+ get_envelope_strategy
+ <
+ Geometry, Strategy
+ >::apply(strategy));
+ }
+};
+
+
+}} // namespace detail::get_rescale_policy
+#endif // DOXYGEN_NO_DETAIL
+
+
template <typename Policy, typename Geometry>
inline Policy get_rescale_policy(Geometry const& geometry)
{
- return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry);
+ typename geometry::strategy::envelope::services::default_strategy
+ <
+ typename geometry::tag<Geometry>::type,
+ typename geometry::cs_tag<Geometry>::type
+ >::type strategy;
+
+ return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry, strategy);
+}
+
+template <typename Policy, typename Geometry, typename Geometry2OrStrategy>
+inline Policy get_rescale_policy(Geometry const& geometry, Geometry2OrStrategy const& geometry2_or_strategy)
+{
+ // if the second argument is a geometry use default strategy
+ // otherwise assume it's envelope strategy for the first argument
+ return detail::get_rescale_policy::get_rescale_policy_geometry_or_strategy
+ <
+ Geometry2OrStrategy
+ > ::template apply<Policy, Geometry>(geometry, geometry2_or_strategy);
}
-template <typename Policy, typename Geometry1, typename Geometry2>
-inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2)
+template <typename Policy, typename Geometry1, typename Geometry2, typename IntersectionStrategy>
+inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ IntersectionStrategy const& strategy)
{
- return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry1, geometry2);
+ return detail::get_rescale_policy::get_rescale_policy
+ <
+ Policy
+ >::apply(geometry1, geometry2,
+ detail::get_rescale_policy::get_envelope_strategy
+ <
+ Geometry1, IntersectionStrategy
+ >::apply(strategy),
+ detail::get_rescale_policy::get_envelope_strategy
+ <
+ Geometry2, IntersectionStrategy
+ >::apply(strategy));
}
diff --git a/boost/geometry/srs/projections/proj/cea.hpp b/boost/geometry/srs/projections/proj/cea.hpp
index 467330e568..14d7ea9a3c 100644
--- a/boost/geometry/srs/projections/proj/cea.hpp
+++ b/boost/geometry/srs/projections/proj/cea.hpp
@@ -164,7 +164,7 @@ namespace projections
par.e = sqrt(par.es);
proj_parm.apa = pj_authset<T>(par.es);
- proj_parm.qp = pj_qsfn(1., par.e, par.one_es);
+ proj_parm.qp = pj_qsfn(T(1), par.e, par.one_es);
}
}
diff --git a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
index 774294b57e..19a3e628d8 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, 2017.
-// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2019.
+// Modifications copyright (c) 2013-2019 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
@@ -62,7 +62,7 @@ struct winding_base_type
template <typename Point, typename PointOfSegment, typename CalculationType>
struct winding_base_type<Point, PointOfSegment, CalculationType, cartesian_tag>
{
- typedef within::cartesian_winding<Point, PointOfSegment, CalculationType> type;
+ typedef within::cartesian_winding<void, void, CalculationType> type;
};
template <typename Point, typename PointOfSegment, typename CalculationType>
@@ -70,8 +70,6 @@ struct winding_base_type<Point, PointOfSegment, CalculationType, spherical_tag>
{
typedef within::detail::spherical_winding_base
<
- Point,
- PointOfSegment,
typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
diff --git a/boost/geometry/strategies/cartesian/box_in_box.hpp b/boost/geometry/strategies/cartesian/box_in_box.hpp
index 4641aafcb1..fef054cdb8 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, 2017.
-// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016, 2017, 2019.
+// Modifications copyright (c) 2016-2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -36,6 +36,11 @@ namespace within
{
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
struct box_within_coord
{
template <typename BoxContainedValue, typename BoxContainingValue>
@@ -63,18 +68,6 @@ struct box_covered_by_coord
};
-template <typename Geometry, std::size_t Dimension, typename CSTag>
-struct box_within_range
- : box_within_coord
-{};
-
-
-template <typename Geometry, std::size_t Dimension, typename CSTag>
-struct box_covered_by_range
- : box_covered_by_coord
-{};
-
-
struct box_within_longitude_diff
{
template <typename CalcT>
@@ -109,7 +102,7 @@ struct box_longitude_range
BoxContainedValue,
BoxContainingValue
>::type calc_t;
- typedef typename coordinate_system<Geometry>::type::units units_t;
+ typedef typename geometry::detail::cs_angular_units<Geometry>::type units_t;
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
if (CoordCheck::apply(bed_min, bed_max, bing_min, bing_max))
@@ -144,35 +137,21 @@ struct box_longitude_range
};
-// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
-template <typename Geometry>
-struct box_within_range<Geometry, 0, spherical_tag>
- : box_longitude_range<Geometry, box_within_coord, box_within_longitude_diff>
-{};
-
-
-template <typename Geometry>
-struct box_covered_by_range<Geometry, 0, spherical_tag>
- : box_longitude_range<Geometry, box_covered_by_coord, box_covered_by_longitude_diff>
-{};
-
-
template
<
template <typename, std::size_t, typename> class SubStrategy,
- typename Box1,
- typename Box2,
+ typename CSTag,
std::size_t Dimension,
std::size_t DimensionCount
>
struct relate_box_box_loop
{
+ template <typename Box1, typename Box2>
static inline bool apply(Box1 const& b_contained, Box2 const& b_containing)
{
assert_dimension_equal<Box1, Box2>();
- typedef typename tag_cast<typename cs_tag<Box1>::type, spherical_tag>::type cs_tag_t;
-
- if (! SubStrategy<Box1, Dimension, cs_tag_t>::apply(
+
+ if (! SubStrategy<Box1, Dimension, CSTag>::apply(
get<min_corner, Dimension>(b_contained),
get<max_corner, Dimension>(b_contained),
get<min_corner, Dimension>(b_containing),
@@ -183,10 +162,9 @@ struct relate_box_box_loop
return false;
}
- return relate_box_box_loop
+ return within::detail::relate_box_box_loop
<
- SubStrategy,
- Box1, Box2,
+ SubStrategy, CSTag,
Dimension + 1, DimensionCount
>::apply(b_contained, b_containing);
}
@@ -195,32 +173,110 @@ struct relate_box_box_loop
template
<
template <typename, std::size_t, typename> class SubStrategy,
- typename Box1,
- typename Box2,
+ typename CSTag,
std::size_t DimensionCount
>
-struct relate_box_box_loop<SubStrategy, Box1, Box2, DimensionCount, DimensionCount>
+struct relate_box_box_loop<SubStrategy, CSTag, DimensionCount, DimensionCount>
{
+ template <typename Box1, typename Box2>
static inline bool apply(Box1 const& , Box2 const& )
{
return true;
}
};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+// for backward compatibility
+template <typename Geometry, std::size_t Dimension, typename CSTag>
+struct box_within_range
+ : within::detail::box_within_coord
+{};
+
+
+template <typename Geometry, std::size_t Dimension, typename CSTag>
+struct box_covered_by_range
+ : within::detail::box_covered_by_coord
+{};
+
+
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
+template <typename Geometry>
+struct box_within_range<Geometry, 0, spherical_tag>
+ : within::detail::box_longitude_range
+ <
+ Geometry,
+ within::detail::box_within_coord,
+ within::detail::box_within_longitude_diff
+ >
+{};
+
+
+template <typename Geometry>
+struct box_covered_by_range<Geometry, 0, spherical_tag>
+ : within::detail::box_longitude_range
+ <
+ Geometry,
+ within::detail::box_covered_by_coord,
+ within::detail::box_covered_by_longitude_diff
+ >
+{};
+
+
+// for backward compatibility
template
<
- typename Box1,
- typename Box2,
+ typename B1,
+ typename B2,
template <typename, std::size_t, typename> class SubStrategy = box_within_range
>
struct box_in_box
{
+ template <typename Box1, typename Box2>
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ typedef typename tag_cast
+ <
+ typename geometry::cs_tag<Box1>::type,
+ spherical_tag
+ >::type cs_tag;
+
+ return within::detail::relate_box_box_loop
+ <
+ SubStrategy, cs_tag,
+ 0, dimension<Box1>::type::value
+ >::apply(box1, box2);
+ }
+};
+
+
+struct cartesian_box_box
+{
+ template <typename Box1, typename Box2>
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ return within::detail::relate_box_box_loop
+ <
+ box_within_range,
+ cartesian_tag,
+ 0, dimension<Box1>::type::value
+ >::apply(box1, box2);
+ }
+};
+
+struct spherical_box_box
+{
+ template <typename Box1, typename Box2>
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
- return relate_box_box_loop
+ return within::detail::relate_box_box_loop
<
- SubStrategy,
- Box1, Box2, 0, dimension<Box1>::type::value
+ box_within_range,
+ spherical_tag,
+ 0, dimension<Box1>::type::value
>::apply(box1, box2);
}
};
@@ -229,6 +285,42 @@ struct box_in_box
} // namespace within
+namespace covered_by
+{
+
+
+struct cartesian_box_box
+{
+ template <typename Box1, typename Box2>
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ return within::detail::relate_box_box_loop
+ <
+ strategy::within::box_covered_by_range,
+ cartesian_tag,
+ 0, dimension<Box1>::type::value
+ >::apply(box1, box2);
+ }
+};
+
+struct spherical_box_box
+{
+ template <typename Box1, typename Box2>
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ return within::detail::relate_box_box_loop
+ <
+ strategy::within::box_covered_by_range,
+ spherical_tag,
+ 0, dimension<Box1>::type::value
+ >::apply(box1, box2);
+ }
+};
+
+
+}
+
+
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
@@ -244,7 +336,7 @@ struct default_strategy
cartesian_tag, cartesian_tag
>
{
- typedef within::box_in_box<BoxContained, BoxContaining> type;
+ typedef cartesian_box_box type;
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
@@ -257,7 +349,7 @@ struct default_strategy
spherical_tag, spherical_tag
>
{
- typedef within::box_in_box<BoxContained, BoxContaining> type;
+ typedef spherical_box_box type;
};
@@ -275,11 +367,7 @@ struct default_strategy
cartesian_tag, cartesian_tag
>
{
- typedef within::box_in_box
- <
- BoxContained, BoxContaining,
- within::box_covered_by_range
- > type;
+ typedef cartesian_box_box type;
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
@@ -292,11 +380,7 @@ struct default_strategy
spherical_tag, spherical_tag
>
{
- typedef within::box_in_box
- <
- BoxContained, BoxContaining,
- within::box_covered_by_range
- > type;
+ typedef spherical_box_box type;
};
diff --git a/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp b/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
index 4da4bc4503..37ae77f2b8 100644
--- a/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
+++ b/boost/geometry/strategies/cartesian/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-2017.
-// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2019.
+// Modifications copyright (c) 2013-2019, 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
@@ -35,6 +35,7 @@
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
@@ -246,22 +247,11 @@ struct disjoint_segment_box_impl
// 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
- >
- {};
+ typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type;
- template <typename Segment, typename Box>
- static inline typename point_in_geometry_strategy<Segment, Box>::type
- get_point_in_geometry_strategy()
+ static inline disjoint_point_box_strategy_type get_disjoint_point_box_strategy()
{
- typedef typename point_in_geometry_strategy<Segment, Box>::type strategy_type;
-
- return strategy_type();
+ return disjoint_point_box_strategy_type();
}
template <typename Segment, typename Box>
diff --git a/boost/geometry/strategies/cartesian/distance_projected_point.hpp b/boost/geometry/strategies/cartesian/distance_projected_point.hpp
index bd4f7130ca..16515a7a2c 100644
--- a/boost/geometry/strategies/cartesian/distance_projected_point.hpp
+++ b/boost/geometry/strategies/cartesian/distance_projected_point.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014, 2018.
-// Modifications copyright (c) 2014-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2018, 2019.
+// Modifications copyright (c) 2014-2019, 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
@@ -38,6 +38,7 @@
#include <boost/geometry/strategies/default_distance_result.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
+#include <boost/geometry/strategies/cartesian/intersection.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
@@ -80,6 +81,26 @@ class projected_point
public :
typedef within::cartesian_point_point equals_point_point_strategy_type;
+ typedef intersection::cartesian_segments
+ <
+ CalculationType
+ > relate_segment_segment_strategy_type;
+
+ static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy()
+ {
+ return relate_segment_segment_strategy_type();
+ }
+
+ typedef within::cartesian_winding
+ <
+ void, void, CalculationType
+ > point_in_geometry_strategy_type;
+
+ static inline point_in_geometry_strategy_type get_point_in_geometry_strategy()
+ {
+ return point_in_geometry_strategy_type();
+ }
+
// The three typedefs below are necessary to calculate distances
// from segments defined in integer coordinates.
diff --git a/boost/geometry/strategies/cartesian/distance_segment_box.hpp b/boost/geometry/strategies/cartesian/distance_segment_box.hpp
index b623822eca..2d7cd2f9b2 100644
--- a/boost/geometry/strategies/cartesian/distance_segment_box.hpp
+++ b/boost/geometry/strategies/cartesian/distance_segment_box.hpp
@@ -14,7 +14,10 @@
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
+#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
+#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
namespace boost { namespace geometry
{
@@ -43,6 +46,8 @@ struct cartesian_segment_box
>
{};
+ typedef cartesian_tag cs_tag;
+
// point-point strategy getters
struct distance_pp_strategy
{
@@ -64,6 +69,23 @@ struct cartesian_segment_box
return typename distance_ps_strategy::type();
}
+ struct distance_pb_strategy
+ {
+ typedef pythagoras_point_box<CalculationType> type;
+ };
+
+ inline typename distance_pb_strategy::type get_distance_pb_strategy() const
+ {
+ return typename distance_pb_strategy::type();
+ }
+
+ typedef side::side_by_triangle<CalculationType> side_strategy_type;
+
+ static inline side_strategy_type get_side_strategy()
+ {
+ return side_strategy_type();
+ }
+
typedef within::cartesian_point_point equals_point_point_strategy_type;
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
diff --git a/boost/geometry/strategies/cartesian/envelope_box.hpp b/boost/geometry/strategies/cartesian/envelope_box.hpp
index c6dd218354..ce723a1b27 100644
--- a/boost/geometry/strategies/cartesian/envelope_box.hpp
+++ b/boost/geometry/strategies/cartesian/envelope_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-2018.
-// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015-2019.
+// Modifications copyright (c) 2015-2019, 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
@@ -32,6 +32,8 @@
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+#include <boost/geometry/strategies/cartesian/expand_box.hpp>
+
#include <boost/geometry/strategies/envelope.hpp>
@@ -78,6 +80,13 @@ namespace strategy { namespace envelope
struct cartesian_box
{
+ typedef strategy::expand::cartesian_box box_expand_strategy_type;
+
+ static inline box_expand_strategy_type get_box_expand_strategy()
+ {
+ return box_expand_strategy_type();
+ }
+
template<typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
diff --git a/boost/geometry/strategies/cartesian/index.hpp b/boost/geometry/strategies/cartesian/index.hpp
new file mode 100644
index 0000000000..80b79bf317
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/index.hpp
@@ -0,0 +1,197 @@
+// Boost.Geometry Index
+//
+// R-tree strategies
+//
+// Copyright (c) 2019, 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_CARTESIAN_INDEX_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INDEX_HPP
+
+
+#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
+#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
+//#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
+#include <boost/geometry/strategies/cartesian/distance_projected_point.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_segment_box.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_box.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_point.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
+#include <boost/geometry/strategies/cartesian/expand_box.hpp>
+#include <boost/geometry/strategies/cartesian/expand_point.hpp>
+#include <boost/geometry/strategies/cartesian/expand_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_point.hpp>
+#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
+
+#include <boost/geometry/strategies/index.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy { namespace index
+{
+
+template
+<
+ typename CalculationType = void
+>
+struct cartesian
+{
+ typedef cartesian_tag cs_tag;
+
+ typedef geometry::strategy::envelope::cartesian_point envelope_point_strategy_type;
+ typedef geometry::strategy::envelope::cartesian_box envelope_box_strategy_type;
+ typedef geometry::strategy::envelope::cartesian_segment
+ <
+ CalculationType
+ > envelope_segment_strategy_type;
+
+ static inline envelope_segment_strategy_type get_envelope_segment_strategy()
+ {
+ return envelope_segment_strategy_type();
+ }
+
+ typedef geometry::strategy::expand::cartesian_point expand_point_strategy_type;
+ typedef geometry::strategy::expand::cartesian_box expand_box_strategy_type;
+ typedef geometry::strategy::expand::cartesian_segment expand_segment_strategy_type;
+
+ static inline expand_segment_strategy_type get_expand_segment_strategy()
+ {
+ return expand_segment_strategy_type();
+ }
+
+ typedef geometry::strategy::covered_by::cartesian_point_box covered_by_point_box_strategy_type;
+ typedef geometry::strategy::covered_by::cartesian_box_box covered_by_box_box_strategy_type;
+ typedef geometry::strategy::within::cartesian_point_point within_point_point_strategy_type;
+ /*
+ typedef geometry::strategy::within::cartesian_point_box within_point_box_strategy_type;
+ typedef geometry::strategy::within::cartesian_box_box within_box_box_strategy_type;
+ typedef geometry::strategy::within::cartesian_winding
+ <
+ void, void, CalculationType
+ > within_point_segment_strategy_type;
+
+ static inline within_point_segment_strategy_type get_within_point_segment_strategy()
+ {
+ return within_point_segment_strategy_type();
+ }
+ */
+
+ // used in equals(Seg, Seg) but only to get_point_in_point_strategy()
+ typedef geometry::strategy::intersection::cartesian_segments
+ <
+ CalculationType
+ > relate_segment_segment_strategy_type;
+
+ static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy()
+ {
+ return relate_segment_segment_strategy_type();
+ }
+
+ // used in intersection_content
+ typedef geometry::strategy::disjoint::cartesian_box_box disjoint_box_box_strategy_type;
+
+ typedef geometry::strategy::distance::comparable::pythagoras
+ <
+ CalculationType
+ > comparable_distance_point_point_strategy_type;
+
+ static inline comparable_distance_point_point_strategy_type get_comparable_distance_point_point_strategy()
+ {
+ return comparable_distance_point_point_strategy_type();
+ }
+
+ typedef geometry::strategy::distance::comparable::pythagoras_point_box
+ <
+ CalculationType
+ > comparable_distance_point_box_strategy_type;
+
+ static inline comparable_distance_point_box_strategy_type get_comparable_distance_point_box_strategy()
+ {
+ return comparable_distance_point_box_strategy_type();
+ }
+
+ // TODO: comparable version should be possible
+ typedef geometry::strategy::distance::projected_point
+ <
+ CalculationType,
+ geometry::strategy::distance::pythagoras<CalculationType>
+ > comparable_distance_point_segment_strategy_type;
+
+ static inline comparable_distance_point_segment_strategy_type get_comparable_distance_point_segment_strategy()
+ {
+ return comparable_distance_point_segment_strategy_type();
+ }
+
+ typedef geometry::strategy::distance::cartesian_segment_box
+ <
+ CalculationType,
+ geometry::strategy::distance::pythagoras<CalculationType>
+ > comparable_distance_segment_box_strategy_type;
+
+ static inline comparable_distance_segment_box_strategy_type get_comparable_distance_segment_box_strategy()
+ {
+ return comparable_distance_segment_box_strategy_type();
+ }
+};
+
+
+namespace services
+{
+
+template <typename Geometry>
+struct default_strategy<Geometry, cartesian_tag>
+{
+ typedef cartesian<> type;
+};
+
+
+// within and relate (MPt, Mls/MPoly)
+template <typename Point1, typename Point2, typename CalculationType>
+struct from_strategy<within::cartesian_winding<Point1, Point2, CalculationType> >
+{
+ typedef strategy::index::cartesian<CalculationType> type;
+
+ static inline type get(within::cartesian_winding<Point1, Point2, CalculationType> const&)
+ {
+ return type();
+ }
+};
+
+// distance (MPt, MPt)
+template <typename CalculationType>
+struct from_strategy<distance::comparable::pythagoras<CalculationType> >
+{
+ typedef strategy::index::cartesian<CalculationType> type;
+
+ static inline type get(distance::comparable::pythagoras<CalculationType> const&)
+ {
+ return type();
+ }
+};
+
+// distance (MPt, Linear/Areal)
+template <typename CalculationType, typename PPStrategy>
+struct from_strategy<distance::projected_point<CalculationType, PPStrategy> >
+{
+ typedef strategy::index::cartesian<CalculationType> type;
+
+ static inline type get(distance::projected_point<CalculationType, PPStrategy> const&)
+ {
+ return type();
+ }
+};
+
+
+} // namespace services
+
+
+}}}} // namespace boost::geometry::strategy::index
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INDEX_HPP
diff --git a/boost/geometry/strategies/cartesian/intersection.hpp b/boost/geometry/strategies/cartesian/intersection.hpp
index 01d1c9433a..33c3da2b67 100644
--- a/boost/geometry/strategies/cartesian/intersection.hpp
+++ b/boost/geometry/strategies/cartesian/intersection.hpp
@@ -76,6 +76,8 @@ template
>
struct cartesian_segments
{
+ typedef cartesian_tag cs_tag;
+
typedef side::side_by_triangle<CalculationType> side_strategy_type;
static inline side_strategy_type get_side_strategy()
@@ -180,6 +182,9 @@ struct cartesian_segments
}
typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type;
+ typedef covered_by::cartesian_point_box covered_by_point_box_strategy_type;
+ typedef within::cartesian_point_box within_point_box_strategy_type;
+ typedef envelope::cartesian_box envelope_box_strategy_type;
typedef expand::cartesian_box expand_box_strategy_type;
template <typename CoordinateType, typename SegmentRatio>
@@ -221,23 +226,21 @@ struct cartesian_segments
// division.
BOOST_GEOMETRY_ASSERT(ratio.denominator() != 0);
- typedef typename promote_integral<CoordinateType>::type promoted_type;
-
- promoted_type const numerator
- = boost::numeric_cast<promoted_type>(ratio.numerator());
- promoted_type const denominator
- = boost::numeric_cast<promoted_type>(ratio.denominator());
- promoted_type const dx_promoted = boost::numeric_cast<promoted_type>(dx);
- promoted_type const dy_promoted = boost::numeric_cast<promoted_type>(dy);
-
- set<0>(point, get<0, 0>(segment) + boost::numeric_cast
- <
- CoordinateType
- >(numerator * dx_promoted / denominator));
- set<1>(point, get<0, 1>(segment) + boost::numeric_cast
- <
- CoordinateType
- >(numerator * dy_promoted / denominator));
+ typedef typename promote_integral<CoordinateType>::type calc_type;
+
+ calc_type const numerator
+ = boost::numeric_cast<calc_type>(ratio.numerator());
+ calc_type const denominator
+ = boost::numeric_cast<calc_type>(ratio.denominator());
+ calc_type const dx_calc = boost::numeric_cast<calc_type>(dx);
+ calc_type const dy_calc = boost::numeric_cast<calc_type>(dy);
+
+ set<0>(point, get<0, 0>(segment)
+ + boost::numeric_cast<CoordinateType>(numerator * dx_calc
+ / denominator));
+ set<1>(point, get<0, 1>(segment)
+ + boost::numeric_cast<CoordinateType>(numerator * dy_calc
+ / denominator));
}
public :
diff --git a/boost/geometry/strategies/cartesian/point_in_point.hpp b/boost/geometry/strategies/cartesian/point_in_point.hpp
index fc849dcd48..fe1713638e 100644
--- a/boost/geometry/strategies/cartesian/point_in_point.hpp
+++ b/boost/geometry/strategies/cartesian/point_in_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, 2017, 2018.
-// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019.
+// Modifications copyright (c) 2013-2019, 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
@@ -76,6 +76,8 @@ namespace strategy { namespace within
struct cartesian_point_point
{
+ typedef cartesian_tag cs_tag;
+
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
diff --git a/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp b/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp
index a8e0de7b7a..e8864df298 100644
--- a/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp
+++ b/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.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 2018.
-// Modifications copyright (c) 2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2018, 2019.
+// Modifications copyright (c) 2018, 2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -47,18 +47,21 @@ namespace strategy { namespace within
template
<
- typename Point,
- typename PointOfSegment = Point,
+ typename Point_, // for backward compatibility
+ typename PointOfSegment_ = Point_, // for backward compatibility
typename CalculationType = void
>
class crossings_multiply
{
- typedef typename select_calculation_type
- <
- Point,
- PointOfSegment,
- CalculationType
- >::type calculation_type;
+ template <typename Point, typename PointOfSegment>
+ struct calculation_type
+ : select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >
+ {};
class flags
{
@@ -79,20 +82,21 @@ class crossings_multiply
public :
- typedef Point point_type;
- typedef PointOfSegment segment_point_type;
typedef flags state_type;
+ template <typename Point, typename PointOfSegment>
static inline bool apply(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
flags& state)
{
- calculation_type const tx = get<0>(point);
- calculation_type const ty = get<1>(point);
- calculation_type const x0 = get<0>(seg1);
- calculation_type const y0 = get<1>(seg1);
- calculation_type const x1 = get<0>(seg2);
- calculation_type const y1 = get<1>(seg2);
+ typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
+
+ calc_t const tx = get<0>(point);
+ calc_t const ty = get<1>(point);
+ calc_t const x0 = get<0>(seg1);
+ calc_t const y0 = get<1>(seg1);
+ calc_t const x1 = get<0>(seg2);
+ calc_t const y1 = get<1>(seg2);
if (state.first)
{
diff --git a/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp b/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp
index 16e7987472..2afa7f1305 100644
--- a/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp
+++ b/boost/geometry/strategies/cartesian/point_in_poly_franklin.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 2018.
-// Modifications copyright (c) 2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2018, 2019.
+// Modifications copyright (c) 2018, 2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -51,48 +51,52 @@ namespace strategy { namespace within
template
<
- typename Point,
- typename PointOfSegment = Point,
+ typename Point_, // for backward compatibility
+ typename PointOfSegment_ = Point_, // for backward compatibility
typename CalculationType = void
>
class franklin
{
- typedef typename select_calculation_type
- <
- Point,
- PointOfSegment,
- CalculationType
- >::type calculation_type;
-
- /*! subclass to keep state */
- class crossings
- {
- bool crosses;
+ template <typename Point, typename PointOfSegment>
+ struct calculation_type
+ : select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >
+ {};
+
+ /*! subclass to keep state */
+ class crossings
+ {
+ bool crosses;
- public :
+ public :
- friend class franklin;
- inline crossings()
- : crosses(false)
- {}
- };
+ friend class franklin;
+ inline crossings()
+ : crosses(false)
+ {}
+ };
public :
- typedef Point point_type;
- typedef PointOfSegment segment_point_type;
typedef crossings state_type;
+ template <typename Point, typename PointOfSegment>
static inline bool apply(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
crossings& state)
{
- calculation_type const& px = get<0>(point);
- calculation_type const& py = get<1>(point);
- calculation_type const& x1 = get<0>(seg1);
- calculation_type const& y1 = get<1>(seg1);
- calculation_type const& x2 = get<0>(seg2);
- calculation_type const& y2 = get<1>(seg2);
+ typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
+
+ calc_t const& px = get<0>(point);
+ calc_t const& py = get<1>(point);
+ calc_t const& x1 = get<0>(seg1);
+ calc_t const& y1 = get<1>(seg1);
+ calc_t const& x2 = get<0>(seg2);
+ calc_t const& y2 = get<1>(seg2);
if (
( (y2 <= py && py < y1) || (y1 <= py && py < y2) )
diff --git a/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp b/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp
index 696a86c984..bb0fe3f81e 100644
--- a/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp
+++ b/boost/geometry/strategies/cartesian/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, 2017, 2018.
-// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018, 2019.
+// Modifications copyright (c) 2013-2019 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
@@ -40,8 +40,8 @@ namespace strategy { namespace within
/*!
\brief Within detection using winding rule in cartesian coordinate system.
\ingroup strategies
-\tparam Point \tparam_point
-\tparam PointOfSegment \tparam_segment_point
+\tparam Point_ \tparam_point
+\tparam PointOfSegment_ \tparam_segment_point
\tparam CalculationType \tparam_calculation
\author Barend Gehrels
@@ -52,20 +52,21 @@ namespace strategy { namespace within
*/
template
<
- typename Point,
- typename PointOfSegment = Point,
+ typename Point_ = void, // for backward compatibility
+ typename PointOfSegment_ = Point_, // for backward compatibility
typename CalculationType = void
>
class cartesian_winding
{
- typedef side::side_by_triangle<CalculationType> side_strategy_type;
-
- typedef typename select_calculation_type
- <
- Point,
- PointOfSegment,
- CalculationType
- >::type calculation_type;
+ template <typename Point, typename PointOfSegment>
+ struct calculation_type
+ : select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >
+ {};
/*! subclass to keep state */
class counter
@@ -89,6 +90,17 @@ class cartesian_winding
};
public:
+ typedef cartesian_tag cs_tag;
+
+ typedef side::side_by_triangle<CalculationType> side_strategy_type;
+
+ static inline side_strategy_type get_side_strategy()
+ {
+ return side_strategy_type();
+ }
+
+ typedef expand::cartesian_point expand_point_strategy_type;
+
typedef typename side_strategy_type::envelope_strategy_type envelope_strategy_type;
static inline envelope_strategy_type get_envelope_strategy()
@@ -118,10 +130,9 @@ public:
typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type;
// Typedefs and static methods to fulfill the concept
- typedef Point point_type;
- typedef PointOfSegment segment_point_type;
typedef counter state_type;
+ template <typename Point, typename PointOfSegment>
static inline bool apply(Point const& point,
PointOfSegment const& s1, PointOfSegment const& s2,
counter& state)
@@ -169,6 +180,7 @@ public:
}
private:
+ template <typename Point, typename PointOfSegment>
static inline int check_segment(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
@@ -183,15 +195,18 @@ private:
return calculate_count(point, seg1, seg2, eq1, eq2);
}
+ template <typename Point, typename PointOfSegment>
static inline bool check_touch(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
counter& state,
bool& eq1, bool& eq2)
{
- calculation_type const px = get<0>(point);
- calculation_type const s1x = get<0>(seg1);
- calculation_type const s2x = get<0>(seg2);
+ typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
+
+ calc_t const px = get<0>(point);
+ calc_t const s1x = get<0>(seg1);
+ calc_t const s2x = get<0>(seg2);
eq1 = math::equals(s1x, px);
eq2 = math::equals(s2x, px);
@@ -200,9 +215,9 @@ private:
// The only thing which has to be done is check if point is ON segment
if (eq1 && eq2)
{
- calculation_type const py = get<1>(point);
- calculation_type const s1y = get<1>(seg1);
- calculation_type const s2y = get<1>(seg2);
+ calc_t const py = get<1>(point);
+ calc_t const s1y = get<1>(seg1);
+ calc_t const s2y = get<1>(seg2);
if ((s1y <= py && s2y >= py) || (s2y <= py && s1y >= py))
{
state.m_touches = true;
@@ -212,14 +227,17 @@ private:
return false;
}
+ template <typename Point, typename PointOfSegment>
static inline int calculate_count(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
bool eq1, bool eq2)
{
- calculation_type const p = get<0>(point);
- calculation_type const s1 = get<0>(seg1);
- calculation_type const s2 = get<0>(seg2);
+ typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
+
+ calc_t const p = get<0>(point);
+ calc_t const s1 = get<0>(seg1);
+ calc_t const s2 = get<0>(seg2);
return eq1 ? (s2 > p ? 1 : -1) // Point on level s1, E/W depending on s2
: eq2 ? (s1 > p ? -1 : 1) // idem
@@ -228,6 +246,7 @@ private:
: 0;
}
+ template <typename Point, typename PointOfSegment>
static inline int side_equal(Point const& point,
PointOfSegment const& se,
int count)
@@ -251,21 +270,13 @@ namespace services
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
- typedef cartesian_winding
- <
- typename geometry::point_type<PointLike>::type,
- typename geometry::point_type<Geometry>::type
- > type;
+ typedef cartesian_winding<> type;
};
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
- typedef cartesian_winding
- <
- typename geometry::point_type<PointLike>::type,
- typename geometry::point_type<Geometry>::type
- > type;
+ typedef cartesian_winding<> type;
};
} // namespace services
@@ -283,21 +294,13 @@ namespace strategy { namespace covered_by { namespace services
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
- typedef within::cartesian_winding
- <
- typename geometry::point_type<PointLike>::type,
- typename geometry::point_type<Geometry>::type
- > type;
+ typedef within::cartesian_winding<> type;
};
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
- typedef within::cartesian_winding
- <
- typename geometry::point_type<PointLike>::type,
- typename geometry::point_type<Geometry>::type
- > type;
+ typedef within::cartesian_winding<> type;
};
}}} // namespace strategy::covered_by::services
diff --git a/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/boost/geometry/strategies/cartesian/side_by_triangle.hpp
index 9760f560c7..e41e4bedbe 100644
--- a/boost/geometry/strategies/cartesian/side_by_triangle.hpp
+++ b/boost/geometry/strategies/cartesian/side_by_triangle.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, 2017, 2018.
-// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017, 2018, 2019.
+// Modifications copyright (c) 2015-2019, 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,6 +71,8 @@ class side_by_triangle
};
public :
+ typedef cartesian_tag cs_tag;
+
typedef strategy::envelope::cartesian<CalculationType> envelope_strategy_type;
static inline envelope_strategy_type get_envelope_strategy()
diff --git a/boost/geometry/strategies/concepts/within_concept.hpp b/boost/geometry/strategies/concepts/within_concept.hpp
index e8b0b767ac..42f2c93037 100644
--- a/boost/geometry/strategies/concepts/within_concept.hpp
+++ b/boost/geometry/strategies/concepts/within_concept.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 2018.
-// Modifications copyright (c) 2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2018, 2019.
+// Modifications copyright (c) 2018, 2019 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
@@ -42,18 +42,20 @@ namespace boost { namespace geometry { namespace concepts
\brief Checks strategy for within (point-in-polygon)
\ingroup within
*/
-template <typename Strategy>
+template <typename Point, typename Polygonal, typename Strategy>
class WithinStrategyPolygonal
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename geometry::point_type<Polygonal>::type point_of_segment;
+
// 1) must define state_type
typedef typename Strategy::state_type state_type;
struct checker
{
template <typename ApplyMethod, typename ResultMethod>
- static void apply(ApplyMethod const&, ResultMethod const& )
+ static void apply(ApplyMethod, ResultMethod)
{
typedef typename parameter_type_of
<
@@ -113,7 +115,8 @@ class WithinStrategyPolygonal
public :
BOOST_CONCEPT_USAGE(WithinStrategyPolygonal)
{
- checker::apply(&Strategy::apply, &Strategy::result);
+ checker::apply(&Strategy::template apply<Point, point_of_segment>,
+ &Strategy::result);
}
#endif
};
@@ -126,7 +129,7 @@ class WithinStrategyPointBox
struct checker
{
template <typename ApplyMethod>
- static void apply(ApplyMethod const&)
+ static void apply(ApplyMethod)
{
typedef typename parameter_type_of
<
@@ -181,7 +184,7 @@ public :
#endif
};
-template <typename Strategy>
+template <typename Box1, typename Box2, typename Strategy>
class WithinStrategyBoxBox
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
@@ -239,7 +242,7 @@ class WithinStrategyBoxBox
public :
BOOST_CONCEPT_USAGE(WithinStrategyBoxBox)
{
- checker::apply(&Strategy::apply);
+ checker::apply(&Strategy::template apply<Box1, Box2>);
}
#endif
};
@@ -270,7 +273,7 @@ template
>
struct check_within<Geometry1, Geometry2, point_tag, AnyTag, areal_tag, Strategy>
{
- BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal<Strategy>) );
+ BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal<Geometry1, Geometry2, Strategy>) );
};
@@ -283,7 +286,7 @@ struct check_within<Geometry1, Geometry2, point_tag, box_tag, areal_tag, Strateg
template <typename Geometry1, typename Geometry2, typename Strategy>
struct check_within<Geometry1, Geometry2, box_tag, box_tag, areal_tag, Strategy>
{
- BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox<Strategy>) );
+ BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox<Geometry1, Geometry2, Strategy>) );
};
diff --git a/boost/geometry/strategies/geographic/buffer_point_circle.hpp b/boost/geometry/strategies/geographic/buffer_point_circle.hpp
index 7e7c8fe81d..51aacefa82 100644
--- a/boost/geometry/strategies/geographic/buffer_point_circle.hpp
+++ b/boost/geometry/strategies/geographic/buffer_point_circle.hpp
@@ -88,6 +88,7 @@ public :
> direct_t;
calculation_type const two_pi = geometry::math::two_pi<calculation_type>();
+ calculation_type const pi = geometry::math::pi<calculation_type>();
calculation_type const diff = two_pi / calculation_type(m_count);
// TODO: after calculation of some angles is corrected,
@@ -96,6 +97,11 @@ public :
for (std::size_t i = 0; i < m_count; i++, angle += diff)
{
+ if (angle > pi)
+ {
+ angle -= two_pi;
+ }
+
typename direct_t::result_type
dir_r = direct_t::apply(get_as_radian<0>(point), get_as_radian<1>(point),
buffer_distance, angle,
diff --git a/boost/geometry/strategies/geographic/disjoint_segment_box.hpp b/boost/geometry/strategies/geographic/disjoint_segment_box.hpp
index 49c80a5e78..c4b8430720 100644
--- a/boost/geometry/strategies/geographic/disjoint_segment_box.hpp
+++ b/boost/geometry/strategies/geographic/disjoint_segment_box.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2017-2018 Oracle and/or its affiliates.
+// Copyright (c) 2017-2019 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
@@ -31,11 +31,12 @@
#include <boost/geometry/srs/spheroid.hpp>
+// TODO: spherical_point_box currently defined in the same file as cartesian
+#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
#include <boost/geometry/strategies/geographic/azimuth.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/normalize.hpp>
-#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
@@ -65,22 +66,11 @@ public:
: m_spheroid(spheroid)
{}
- template <typename Segment, typename Box>
- struct point_in_geometry_strategy
- : services::default_strategy
- <
- typename point_type<Segment>::type,
- Box
- >
- {};
-
- template <typename Segment, typename Box>
- static inline typename point_in_geometry_strategy<Segment, Box>::type
- get_point_in_geometry_strategy()
+ typedef covered_by::spherical_point_box disjoint_point_box_strategy_type;
+
+ static inline disjoint_point_box_strategy_type get_disjoint_point_box_strategy()
{
- typedef typename point_in_geometry_strategy<Segment, Box>::type strategy_type;
-
- return strategy_type();
+ return disjoint_point_box_strategy_type();
}
template <typename Segment, typename Box>
diff --git a/boost/geometry/strategies/geographic/distance_cross_track.hpp b/boost/geometry/strategies/geographic/distance_cross_track.hpp
index 53942529bf..f0ad2b16a1 100644
--- a/boost/geometry/strategies/geographic/distance_cross_track.hpp
+++ b/boost/geometry/strategies/geographic/distance_cross_track.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2016-2018, Oracle and/or its affiliates.
+// Copyright (c) 2016-2019, 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
@@ -34,6 +34,7 @@
#include <boost/geometry/strategies/geographic/azimuth.hpp>
#include <boost/geometry/strategies/geographic/distance.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/strategies/geographic/intersection.hpp>
#include <boost/geometry/formulas/vincenty_direct.hpp>
@@ -44,6 +45,7 @@
#include <boost/geometry/formulas/result_direct.hpp>
#include <boost/geometry/formulas/mean_radius.hpp>
+#include <boost/geometry/formulas/spherical.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
#include <boost/geometry/io/dsv/write.hpp>
@@ -63,6 +65,8 @@ namespace boost { namespace geometry
namespace strategy { namespace distance
{
+namespace detail
+{
/*!
\brief Strategy functor for distance point to segment calculation on ellipsoid
Algorithm uses direct and inverse geodesic problems as subroutines.
@@ -82,6 +86,7 @@ template
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void,
+ bool Bisection = false,
bool EnableClosestPoint = false
>
class geographic_cross_track
@@ -89,6 +94,29 @@ class geographic_cross_track
public :
typedef within::spherical_point_point equals_point_point_strategy_type;
+ typedef intersection::geographic_segments
+ <
+ FormulaPolicy,
+ strategy::default_order<FormulaPolicy>::value,
+ Spheroid,
+ CalculationType
+ > relate_segment_segment_strategy_type;
+
+ inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy() const
+ {
+ return relate_segment_segment_strategy_type(m_spheroid);
+ }
+
+ typedef within::geographic_winding
+ <
+ void, void, FormulaPolicy, Spheroid, CalculationType
+ > point_in_geometry_strategy_type;
+
+ inline point_in_geometry_strategy_type get_point_in_geometry_strategy() const
+ {
+ return point_in_geometry_strategy_type(m_spheroid);
+ }
+
template <typename Point, typename PointOfSegment>
struct return_type
: promote_floating_point
@@ -112,15 +140,15 @@ public :
{
typedef typename geometry::detail::cs_angular_units<Point>::type units_type;
- return (apply<units_type>(get<0>(sp1), get<1>(sp1),
- get<0>(sp2), get<1>(sp2),
- get<0>(p), get<1>(p),
+ return (apply<units_type>(get_as_radian<0>(sp1), get_as_radian<1>(sp1),
+ get_as_radian<0>(sp2), get_as_radian<1>(sp2),
+ get_as_radian<0>(p), get_as_radian<1>(p),
m_spheroid)).distance;
}
// points on a meridian not crossing poles
template <typename CT>
- inline CT vertical_or_meridian(CT lat1, CT lat2) const
+ inline CT vertical_or_meridian(CT const& lat1, CT const& lat2) const
{
typedef typename formula::meridian_inverse
<
@@ -132,6 +160,11 @@ public :
m_spheroid);
}
+ Spheroid const& model() const
+ {
+ return m_spheroid;
+ }
+
private :
template <typename CT>
@@ -150,7 +183,7 @@ private :
template <typename CT>
result_distance_point_segment<CT>
- static inline non_iterative_case(CT lon, CT lat, CT distance)
+ static inline non_iterative_case(CT const& lon, CT const& lat, CT const& distance)
{
result_distance_point_segment<CT> result;
result.distance = distance;
@@ -165,8 +198,8 @@ private :
template <typename CT>
result_distance_point_segment<CT>
- static inline non_iterative_case(CT lon1, CT lat1, //p1
- CT lon2, CT lat2, //p2
+ static inline non_iterative_case(CT const& lon1, CT const& lat1, //p1
+ CT const& lon2, CT const& lat2, //p2
Spheroid const& spheroid)
{
CT distance = geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
@@ -176,7 +209,7 @@ private :
}
template <typename CT>
- CT static inline normalize(CT g4, CT& der)
+ CT static inline normalize(CT const& g4, CT& der)
{
CT const pi = math::pi<CT>();
if (g4 < -1.25*pi)//close to -270
@@ -205,22 +238,236 @@ private :
return g4 - pi/2;
}
- template <typename Units, typename CT>
- result_distance_point_segment<CT>
- static inline apply(CT lon1, CT lat1, //p1
- CT lon2, CT lat2, //p2
- CT lon3, CT lat3, //query point p3
- Spheroid const& spheroid)
+ template <typename CT>
+ static void bisection(CT const& lon1, CT const& lat1, //p1
+ CT const& lon2, CT const& lat2, //p2
+ CT const& lon3, CT const& lat3, //query point p3
+ Spheroid const& spheroid,
+ CT const& s14_start, CT const& a12,
+ result_distance_point_segment<CT>& result)
+ {
+ typedef typename FormulaPolicy::template direct<CT, true, false, false, false>
+ direct_distance_type;
+ typedef typename FormulaPolicy::template inverse<CT, true, false, false, false, false>
+ inverse_distance_type;
+
+ geometry::formula::result_direct<CT> res14;
+
+ int counter = 0; // robustness
+ bool dist_improve = true;
+
+ CT pl_lon = lon1;
+ CT pl_lat = lat1;
+ CT pr_lon = lon2;
+ CT pr_lat = lat2;
+
+ CT s14 = s14_start;
+
+ do{
+ // Solve the direct problem to find p4 (GEO)
+ res14 = direct_distance_type::apply(lon1, lat1, s14, a12, spheroid);
+
+#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
+ std::cout << "dist(pl,p3)="
+ << inverse_distance_type::apply(lon3, lat3,
+ pr_lon, pr_lat,
+ spheroid).distance
+ << std::endl;
+ std::cout << "dist(pr,p3)="
+ << inverse_distance_type::apply(lon3, lat3,
+ pr_lon, pr_lat,
+ spheroid).distance
+ << std::endl;
+#endif
+ if (inverse_distance_type::apply(lon3, lat3, pl_lon, pl_lat, spheroid).distance
+ < inverse_distance_type::apply(lon3, lat3, pr_lon, pr_lat, spheroid).distance)
+ {
+ s14 -= inverse_distance_type::apply(res14.lon2, res14.lat2, pl_lon, pl_lat,
+ spheroid).distance/2;
+ pr_lon = res14.lon2;
+ pr_lat = res14.lat2;
+ }
+ else
+ {
+ s14 += inverse_distance_type::apply(res14.lon2, res14.lat2, pr_lon, pr_lat,
+ spheroid).distance/2;
+ pl_lon = res14.lon2;
+ pl_lat = res14.lat2;
+ }
+
+ CT new_distance = inverse_distance_type::apply(lon3, lat3,
+ res14.lon2, res14.lat2,
+ spheroid).distance;
+
+ dist_improve = new_distance != result.distance;
+
+#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
+ std::cout << "p4=" << res14.lon2 * math::r2d<CT>() <<
+ "," << res14.lat2 * math::r2d<CT>() << std::endl;
+ std::cout << "pl=" << pl_lon * math::r2d<CT>() << "," << pl_lat * math::r2d<CT>()<< std::endl;
+ std::cout << "pr=" << pr_lon * math::r2d<CT>() << "," << pr_lat * math::r2d<CT>() << std::endl;
+ std::cout << "new_s14=" << s14 << std::endl;
+ std::cout << std::setprecision(16) << "result.distance =" << result.distance << std::endl;
+ std::cout << std::setprecision(16) << "new_distance =" << new_distance << std::endl;
+ std::cout << "---------end of step " << counter << std::endl<< std::endl;
+ if (!dist_improve)
+ {
+ std::cout << "Stop msg: res34.distance >= prev_distance" << std::endl;
+ }
+ if (counter == BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS)
+ {
+ std::cout << "Stop msg: counter" << std::endl;
+ }
+#endif
+
+ result.distance = new_distance;
+
+ } while (dist_improve
+ && counter++ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS);
+ }
+
+ template <typename CT>
+ static void newton(CT const& lon1, CT const& lat1, //p1
+ CT const& lon2, CT const& lat2, //p2
+ CT const& lon3, CT const& lat3, //query point p3
+ Spheroid const& spheroid,
+ CT const& s14_start, CT const& a12,
+ result_distance_point_segment<CT>& result)
{
typedef typename FormulaPolicy::template inverse<CT, true, true, false, true, true>
inverse_distance_azimuth_quantities_type;
typedef typename FormulaPolicy::template inverse<CT, false, true, false, false, false>
- inverse_azimuth_type;
- typedef typename FormulaPolicy::template inverse<CT, false, true, true, false, false>
- inverse_azimuth_reverse_type;
+ inverse_dist_azimuth_type;
typedef typename FormulaPolicy::template direct<CT, true, false, false, false>
direct_distance_type;
+ CT const half_pi = math::pi<CT>() / CT(2);
+ CT prev_distance;
+ geometry::formula::result_direct<CT> res14;
+ geometry::formula::result_inverse<CT> res34;
+ res34.distance = -1;
+
+ int counter = 0; // robustness
+ CT g4;
+ CT delta_g4 = 0;
+ bool dist_improve = true;
+ CT s14 = s14_start;
+
+ do{
+ prev_distance = res34.distance;
+
+ // Solve the direct problem to find p4 (GEO)
+ res14 = direct_distance_type::apply(lon1, lat1, s14, a12, spheroid);
+
+ // Solve an inverse problem to find g4
+ // g4 is the angle between segment (p1,p2) and segment (p3,p4) that meet on p4 (GEO)
+
+ CT a4 = inverse_dist_azimuth_type::apply(res14.lon2, res14.lat2,
+ lon2, lat2, spheroid).azimuth;
+ res34 = inverse_distance_azimuth_quantities_type::apply(res14.lon2, res14.lat2,
+ lon3, lat3, spheroid);
+ g4 = res34.azimuth - a4;
+
+ CT M43 = res34.geodesic_scale; // cos(s14/earth_radius) is the spherical limit
+ CT m34 = res34.reduced_length;
+
+ if (m34 != 0)
+ {
+ CT der = (M43 / m34) * sin(g4);
+ delta_g4 = normalize(g4, der);
+ s14 -= der != 0 ? delta_g4 / der : 0;
+ }
+
+ result.distance = res34.distance;
+
+ dist_improve = prev_distance > res34.distance || prev_distance == -1;
+ if (!dist_improve)
+ {
+ result.distance = prev_distance;
+ }
+
+#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
+ std::cout << "p4=" << res14.lon2 * math::r2d<CT>() <<
+ "," << res14.lat2 * math::r2d<CT>() << std::endl;
+ std::cout << "a34=" << res34.azimuth * math::r2d<CT>() << std::endl;
+ std::cout << "a4=" << a4 * math::r2d<CT>() << std::endl;
+ std::cout << "g4(normalized)=" << g4 * math::r2d<CT>() << std::endl;
+ std::cout << "delta_g4=" << delta_g4 * math::r2d<CT>() << std::endl;
+ std::cout << "der=" << der << std::endl;
+ std::cout << "M43=" << M43 << std::endl;
+ std::cout << "m34=" << m34 << std::endl;
+ std::cout << "new_s14=" << s14 << std::endl;
+ std::cout << std::setprecision(16) << "dist =" << res34.distance << std::endl;
+ std::cout << "---------end of step " << counter << std::endl<< std::endl;
+ if (g4 == half_pi)
+ {
+ std::cout << "Stop msg: g4 == half_pi" << std::endl;
+ }
+ if (!dist_improve)
+ {
+ std::cout << "Stop msg: res34.distance >= prev_distance" << std::endl;
+ }
+ if (delta_g4 == 0)
+ {
+ std::cout << "Stop msg: delta_g4 == 0" << std::endl;
+ }
+ if (counter == BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS)
+ {
+ std::cout << "Stop msg: counter" << std::endl;
+ }
+#endif
+
+ } while (g4 != half_pi
+ && dist_improve
+ && delta_g4 != 0
+ && counter++ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS);
+#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
+ std::cout << "distance=" << res34.distance << std::endl;
+
+ std::cout << "s34(geo) ="
+ << inverse_distance_azimuth_quantities_type::apply(res14.lon2, res14.lat2, lon3, lat3, spheroid).distance
+ << ", p4=(" << res14.lon2 * math::r2d<double>() << ","
+ << res14.lat2 * math::r2d<double>() << ")"
+ << std::endl;
+
+ CT s31 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon1, lat1, spheroid).distance;
+ CT s32 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon2, lat2, spheroid).distance;
+
+ CT a4 = inverse_dist_azimuth_type::apply(res14.lon2, res14.lat2, lon2, lat2, spheroid).azimuth;
+ geometry::formula::result_direct<CT> res4 = direct_distance_type::apply(res14.lon2, res14.lat2, .04, a4, spheroid);
+ CT p4_plus = inverse_distance_azimuth_quantities_type::apply(res4.lon2, res4.lat2, lon3, lat3, spheroid).distance;
+
+ geometry::formula::result_direct<CT> res1 = direct_distance_type::apply(lon1, lat1, s14-.04, a12, spheroid);
+ CT p4_minus = inverse_distance_azimuth_quantities_type::apply(res1.lon2, res1.lat2, lon3, lat3, spheroid).distance;
+
+ std::cout << "s31=" << s31 << "\ns32=" << s32
+ << "\np4_plus=" << p4_plus << ", p4=(" << res4.lon2 * math::r2d<double>() << "," << res4.lat2 * math::r2d<double>() << ")"
+ << "\np4_minus=" << p4_minus << ", p4=(" << res1.lon2 * math::r2d<double>() << "," << res1.lat2 * math::r2d<double>() << ")"
+ << std::endl;
+
+ if (res34.distance <= p4_plus && res34.distance <= p4_minus)
+ {
+ std::cout << "Closest point computed" << std::endl;
+ }
+ else
+ {
+ std::cout << "There is a closer point nearby" << std::endl;
+ }
+#endif
+ }
+
+ template <typename Units, typename CT>
+ result_distance_point_segment<CT>
+ static inline apply(CT const& lo1, CT const& la1, //p1
+ CT const& lo2, CT const& la2, //p2
+ CT const& lo3, CT const& la3, //query point p3
+ Spheroid const& spheroid)
+ {
+ typedef typename FormulaPolicy::template inverse<CT, true, true, false, false, false>
+ inverse_dist_azimuth_type;
+ typedef typename FormulaPolicy::template inverse<CT, true, true, true, false, false>
+ inverse_dist_azimuth_reverse_type;
+
CT const earth_radius = geometry::formula::mean_radius<CT>(spheroid);
result_distance_point_segment<CT> result;
@@ -231,13 +478,12 @@ private :
CT const half_pi = pi / CT(2);
CT const c0 = CT(0);
- // Convert to radians
- lon1 = math::as_radian<Units>(lon1);
- lat1 = math::as_radian<Units>(lat1);
- lon2 = math::as_radian<Units>(lon2);
- lat2 = math::as_radian<Units>(lat2);
- lon3 = math::as_radian<Units>(lon3);
- lat3 = math::as_radian<Units>(lat3);
+ CT lon1 = lo1;
+ CT lat1 = la1;
+ CT lon2 = lo2;
+ CT lat2 = la2;
+ CT lon3 = lo3;
+ CT lat3 = la3;
if (lon1 > lon2)
{
@@ -306,49 +552,44 @@ private :
std::cout << "Meridian segment crossing pole" << std::endl;
#endif
CT sign_non_zero = lat3 >= c0 ? 1 : -1;
- result_distance_point_segment<CT> d1 =
+ result_distance_point_segment<CT> res13 =
apply<geometry::radian>(lon1, lat1,
lon1, half_pi * sign_non_zero,
lon3, lat3, spheroid);
- result_distance_point_segment<CT> d2 =
+ result_distance_point_segment<CT> res23 =
apply<geometry::radian>(lon2, lat2,
lon2, half_pi * sign_non_zero,
lon3, lat3, spheroid);
- if (d1.distance < d2.distance)
+ if (res13.distance < res23.distance)
{
- return d1;
+ return res13;
}
else
{
- return d2;
+ return res23;
}
}
- CT d1 = geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
- ::apply(lon1, lat1, lon3, lat3, spheroid);
-
- CT d3 = geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
- ::apply(lon1, lat1, lon2, lat2, spheroid);
+ geometry::formula::result_inverse<CT> res12 =
+ inverse_dist_azimuth_reverse_type::apply(lon1, lat1, lon2, lat2, spheroid);
+ geometry::formula::result_inverse<CT> res13 =
+ inverse_dist_azimuth_type::apply(lon1, lat1, lon3, lat3, spheroid);
- if (geometry::math::equals(d3, c0))
+ if (geometry::math::equals(res12.distance, c0))
{
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "Degenerate segment" << std::endl;
- std::cout << "distance between points=" << d1 << std::endl;
+ std::cout << "distance between points=" << res13.distance << std::endl;
#endif
- return non_iterative_case(lon1, lat2, d1);
- }
+ typename meridian_inverse::result res =
+ meridian_inverse::apply(lon1, lat1, lon3, lat3, spheroid);
- CT d2 = geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
- ::apply(lon2, lat2, lon3, lat3, spheroid);
+ return non_iterative_case(lon1, lat2,
+ res.meridian ? res.distance : res13.distance);
+ }
// Compute a12 (GEO)
- geometry::formula::result_inverse<CT> res12 =
- inverse_azimuth_reverse_type::apply(lon1, lat1, lon2, lat2, spheroid);
- CT a12 = res12.azimuth;
- CT a13 = inverse_azimuth_type::apply(lon1, lat1, lon3, lat3, spheroid).azimuth;
-
- CT a312 = a13 - a12;
+ CT a312 = res13.azimuth - res12.azimuth;
// TODO: meridian case optimization
if (geometry::math::equals(a312, c0) && meridian_not_crossing_pole)
@@ -364,11 +605,11 @@ private :
}
}
- CT projection1 = cos( a312 ) * d1 / d3;
+ CT projection1 = cos( a312 ) * res13.distance / res12.distance;
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
- std::cout << "a1=" << a12 * math::r2d<CT>() << std::endl;
- std::cout << "a13=" << a13 * math::r2d<CT>() << std::endl;
+ std::cout << "a1=" << res12.azimuth * math::r2d<CT>() << std::endl;
+ std::cout << "a13=" << res13.azimuth * math::r2d<CT>() << std::endl;
std::cout << "a312=" << a312 * math::r2d<CT>() << std::endl;
std::cout << "cos(a312)=" << cos(a312) << std::endl;
std::cout << "projection 1=" << projection1 << std::endl;
@@ -381,19 +622,19 @@ private :
#endif
// projection of p3 on geodesic spanned by segment (p1,p2) fall
// outside of segment on the side of p1
+
return non_iterative_case(lon1, lat1, lon3, lat3, spheroid);
}
- CT a21 = res12.reverse_azimuth - pi;
- CT a23 = inverse_azimuth_type::apply(lon2, lat2, lon3, lat3, spheroid).azimuth;
-
- CT a321 = a23 - a21;
+ geometry::formula::result_inverse<CT> res23 =
+ inverse_dist_azimuth_type::apply(lon2, lat2, lon3, lat3, spheroid);
- CT projection2 = cos( a321 ) * d2 / d3;
+ CT a321 = res23.azimuth - res12.reverse_azimuth + pi;
+ CT projection2 = cos( a321 ) * res23.distance / res12.distance;
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
- std::cout << "a21=" << a21 * math::r2d<CT>() << std::endl;
- std::cout << "a23=" << a23 * math::r2d<CT>() << std::endl;
+ std::cout << "a21=" << res12.reverse_azimuth * math::r2d<CT>() << std::endl;
+ std::cout << "a23=" << res23.azimuth * math::r2d<CT>() << std::endl;
std::cout << "a321=" << a321 * math::r2d<CT>() << std::endl;
std::cout << "cos(a321)=" << cos(a321) << std::endl;
std::cout << "projection 2=" << projection2 << std::endl;
@@ -421,139 +662,49 @@ private :
point p3 = point(lon3, lat3);
geometry::strategy::distance::cross_track<CT> cross_track(earth_radius);
- CT s34 = cross_track.apply(p3, p1, p2);
+ CT s34_sph = cross_track.apply(p3, p1, p2);
geometry::strategy::distance::haversine<CT> str(earth_radius);
- CT s13 = str.apply(p1, p3);
+ CT s13_sph = str.apply(p1, p3);
//CT s14 = acos( cos(s13/earth_radius) / cos(s34/earth_radius) ) * earth_radius;
- CT cos_frac = cos(s13/earth_radius) / cos(s34/earth_radius);
- CT s14 = cos_frac >= 1 ? CT(0)
- : cos_frac <= -1 ? pi * earth_radius
- : acos(cos_frac) * earth_radius;
-
-#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
- std::cout << "s34=" << s34 << std::endl;
- std::cout << "s13=" << s13 << std::endl;
- std::cout << "s14=" << s14 << std::endl;
- std::cout << "===============" << std::endl;
-#endif
-
- // Update s14 (using Newton method)
- CT prev_distance;
- geometry::formula::result_direct<CT> res14;
- geometry::formula::result_inverse<CT> res34;
- res34.distance = -1;
+ CT cos_frac = cos(s13_sph / earth_radius) / cos(s34_sph / earth_radius);
+ CT s14_sph = cos_frac >= 1 ? CT(0)
+ : cos_frac <= -1 ? pi * earth_radius
+ : acos(cos_frac) * earth_radius;
- int counter = 0; // robustness
- CT g4;
- CT delta_g4;
- bool dist_improve = true;
+ CT a12_sph = geometry::formula::spherical_azimuth<>(lon1, lat1, lon2, lat2);
- do{
- prev_distance = res34.distance;
+ geometry::formula::result_direct<CT> res
+ = geometry::formula::spherical_direct<true, false>
+ (lon1, lat1, s14_sph, a12_sph, srs::sphere<CT>(earth_radius));
- // Solve the direct problem to find p4 (GEO)
- res14 = direct_distance_type::apply(lon1, lat1, s14, a12, spheroid);
-
- // Solve an inverse problem to find g4
- // g4 is the angle between segment (p1,p2) and segment (p3,p4) that meet on p4 (GEO)
-
- CT a4 = inverse_azimuth_type::apply(res14.lon2, res14.lat2,
- lon2, lat2, spheroid).azimuth;
- res34 = inverse_distance_azimuth_quantities_type::apply(res14.lon2, res14.lat2,
- lon3, lat3, spheroid);
- g4 = res34.azimuth - a4;
-
- CT M43 = res34.geodesic_scale; // cos(s14/earth_radius) is the spherical limit
- CT m34 = res34.reduced_length;
- CT der = (M43 / m34) * sin(g4);
-
- //normalize
- delta_g4 = normalize(g4, der);
- s14 = s14 - delta_g4 / der;
- result.distance = res34.distance;
-
- dist_improve = prev_distance > res34.distance || prev_distance == -1;
- if (!dist_improve)
- {
- result.distance = prev_distance;
- }
+ // this is what postgis (version 2.5) returns
+ // geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
+ // ::apply(lon3, lat3, res.lon2, res.lat2, spheroid);
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
- std::cout << "p4=" << res14.lon2 * math::r2d<CT>() <<
- "," << res14.lat2 * math::r2d<CT>() << std::endl;
- std::cout << "a34=" << res34.azimuth * math::r2d<CT>() << std::endl;
- std::cout << "a4=" << a4 * math::r2d<CT>() << std::endl;
- std::cout << "g4(normalized)=" << g4 * math::r2d<CT>() << std::endl;
- std::cout << "delta_g4=" << delta_g4 * math::r2d<CT>() << std::endl;
- std::cout << "der=" << der << std::endl;
- std::cout << "M43=" << M43 << std::endl;
- std::cout << "spherical limit=" << cos(s14/earth_radius) << std::endl;
- std::cout << "m34=" << m34 << std::endl;
- std::cout << "new_s14=" << s14 << std::endl;
- std::cout << std::setprecision(16) << "dist =" << res34.distance << std::endl;
- std::cout << "---------end of step " << counter << std::endl<< std::endl;
- if (g4 == half_pi)
- {
- std::cout << "Stop msg: g4 == half_pi" << std::endl;
- }
- if (!dist_improve)
- {
- std::cout << "Stop msg: res34.distance >= prev_distance" << std::endl;
- }
- if (delta_g4 == 0)
- {
- std::cout << "Stop msg: delta_g4 == 0" << std::endl;
- }
- if (counter == BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS)
- {
- std::cout << "Stop msg: counter" << std::endl;
- }
+ std::cout << "s34=" << s34_sph << std::endl;
+ std::cout << "s13=" << res13.distance << std::endl;
+ std::cout << "s14=" << s14_sph << std::endl;
+ std::cout << "===============" << std::endl;
#endif
- } while (g4 != half_pi
- && dist_improve
- && delta_g4 != 0
- && counter++ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS);
-
-#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
- std::cout << "distance=" << res34.distance << std::endl;
-
- point p4(res14.lon2, res14.lat2);
- CT s34_sph = str.apply(p4, p3);
-
- std::cout << "s34(sph) =" << s34_sph << std::endl;
- std::cout << "s34(geo) ="
- << inverse_distance_azimuth_quantities_type::apply(get<0>(p4), get<1>(p4), lon3, lat3, spheroid).distance
- << ", p4=(" << get<0>(p4) * math::r2d<double>() << ","
- << get<1>(p4) * math::r2d<double>() << ")"
- << std::endl;
-
- CT s31 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon1, lat1, spheroid).distance;
- CT s32 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon2, lat2, spheroid).distance;
-
- CT a4 = inverse_azimuth_type::apply(get<0>(p4), get<1>(p4), lon2, lat2, spheroid).azimuth;
- geometry::formula::result_direct<CT> res4 = direct_distance_type::apply(get<0>(p4), get<1>(p4), .04, a4, spheroid);
- CT p4_plus = inverse_distance_azimuth_quantities_type::apply(res4.lon2, res4.lat2, lon3, lat3, spheroid).distance;
-
- geometry::formula::result_direct<CT> res1 = direct_distance_type::apply(lon1, lat1, s14-.04, a12, spheroid);
- CT p4_minus = inverse_distance_azimuth_quantities_type::apply(res1.lon2, res1.lat2, lon3, lat3, spheroid).distance;
-
- std::cout << "s31=" << s31 << "\ns32=" << s32
- << "\np4_plus=" << p4_plus << ", p4=(" << res4.lon2 * math::r2d<double>() << "," << res4.lat2 * math::r2d<double>() << ")"
- << "\np4_minus=" << p4_minus << ", p4=(" << res1.lon2 * math::r2d<double>() << "," << res1.lat2 * math::r2d<double>() << ")"
- << std::endl;
+ // Update s14 (using Newton method)
- if (res34.distance <= p4_plus && res34.distance <= p4_minus)
+ if (Bisection)
{
- std::cout << "Closest point computed" << std::endl;
+ bisection<CT>(lon1, lat1, lon2, lat2, lon3, lat3,
+ spheroid, res12.distance/2, res12.azimuth, result);
}
else
{
- std::cout << "There is a closer point nearby" << std::endl;
+ CT s14_start = geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
+ ::apply(lon1, lat1, res.lon2, res.lat2, spheroid);
+
+ newton<CT>(lon1, lat1, lon2, lat2, lon3, lat3,
+ spheroid, s14_start, res12.azimuth, result);
}
-#endif
return result;
}
@@ -561,7 +712,37 @@ private :
Spheroid m_spheroid;
};
+} // namespace detail
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic_cross_track
+ : public detail::geographic_cross_track
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType,
+ false,
+ false
+ >
+{
+public :
+ explicit geographic_cross_track(Spheroid const& spheroid = Spheroid())
+ :
+ detail::geographic_cross_track<
+ FormulaPolicy,
+ Spheroid,
+ CalculationType,
+ false,
+ false
+ >(spheroid)
+ {}
+};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
@@ -595,6 +776,17 @@ struct tag<geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> >
typedef strategy_tag_distance_point_segment type;
};
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType,
+ bool Bisection
+>
+struct tag<detail::geographic_cross_track<FormulaPolicy, Spheroid, CalculationType, Bisection> >
+{
+ typedef strategy_tag_distance_point_segment type;
+};
//return types
template <typename FormulaPolicy, typename P, typename PS>
@@ -625,6 +817,19 @@ struct return_type<geographic_cross_track<FormulaPolicy, Spheroid, CalculationTy
: geographic_cross_track<FormulaPolicy, Spheroid, CalculationType>::template return_type<P, PS>
{};
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType,
+ bool Bisection,
+ typename P,
+ typename PS
+>
+struct return_type<detail::geographic_cross_track<FormulaPolicy, Spheroid, CalculationType, Bisection>, P, PS>
+ : detail::geographic_cross_track<FormulaPolicy, Spheroid, CalculationType, Bisection>::template return_type<P, PS>
+{};
+
//comparable types
template
<
@@ -640,6 +845,22 @@ struct comparable_type<geographic_cross_track<FormulaPolicy, Spheroid, Calculati
> type;
};
+
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType,
+ bool Bisection
+>
+struct comparable_type<detail::geographic_cross_track<FormulaPolicy, Spheroid, CalculationType, Bisection> >
+{
+ typedef detail::geographic_cross_track
+ <
+ FormulaPolicy, Spheroid, CalculationType, Bisection
+ > type;
+};
+
template
<
typename FormulaPolicy,
@@ -656,6 +877,23 @@ public :
}
};
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType,
+ bool Bisection
+>
+struct get_comparable<detail::geographic_cross_track<FormulaPolicy, Spheroid, CalculationType, Bisection> >
+{
+public :
+ static inline detail::geographic_cross_track<FormulaPolicy, Spheroid, CalculationType, Bisection>
+ apply(detail::geographic_cross_track<FormulaPolicy, Spheroid, CalculationType, Bisection> const& strategy)
+ {
+ return strategy;
+ }
+};
+
template
<
diff --git a/boost/geometry/strategies/geographic/distance_segment_box.hpp b/boost/geometry/strategies/geographic/distance_segment_box.hpp
index 615f938739..99b181fa25 100644
--- a/boost/geometry/strategies/geographic/distance_segment_box.hpp
+++ b/boost/geometry/strategies/geographic/distance_segment_box.hpp
@@ -16,9 +16,10 @@
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
#include <boost/geometry/strategies/distance.hpp>
-#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/geographic/azimuth.hpp>
#include <boost/geometry/strategies/geographic/distance_cross_track.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/strategies/geographic/side.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
#include <boost/geometry/strategies/spherical/distance_segment_box.hpp>
@@ -55,6 +56,8 @@ struct geographic_segment_box
>
{};
+ typedef geographic_tag cs_tag;
+
// point-point strategy getters
struct distance_pp_strategy
{
@@ -83,6 +86,33 @@ struct geographic_segment_box
return distance_type(m_spheroid);
}
+ struct distance_pb_strategy
+ {
+ typedef geographic_cross_track_point_box
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType
+ > type;
+ };
+
+ inline typename distance_pb_strategy::type get_distance_pb_strategy() const
+ {
+ return typename distance_pb_strategy::type(m_spheroid);
+ }
+
+ typedef side::geographic
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType
+ > side_strategy_type;
+
+ inline side_strategy_type get_side_strategy() const
+ {
+ return side_strategy_type(m_spheroid);
+ }
+
typedef within::spherical_point_point equals_point_point_strategy_type;
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
diff --git a/boost/geometry/strategies/geographic/index.hpp b/boost/geometry/strategies/geographic/index.hpp
new file mode 100644
index 0000000000..202f0620df
--- /dev/null
+++ b/boost/geometry/strategies/geographic/index.hpp
@@ -0,0 +1,216 @@
+// Boost.Geometry Index
+//
+// R-tree strategies
+//
+// Copyright (c) 2019, 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_INDEX_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INDEX_HPP
+
+
+#include <boost/geometry/strategies/geographic/distance.hpp>
+#include <boost/geometry/strategies/geographic/distance_andoyer.hpp> // backward compatibility
+#include <boost/geometry/strategies/geographic/distance_cross_track.hpp>
+#include <boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp>
+#include <boost/geometry/strategies/geographic/distance_segment_box.hpp>
+#include <boost/geometry/strategies/geographic/distance_thomas.hpp> // backward compatibility
+#include <boost/geometry/strategies/geographic/distance_vincenty.hpp> // backward compatibility
+#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
+#include <boost/geometry/strategies/geographic/expand_segment.hpp>
+#include <boost/geometry/strategies/geographic/intersection.hpp>
+#include <boost/geometry/strategies/geographic/point_in_poly_winding.hpp>
+
+#include <boost/geometry/strategies/spherical/index.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy { namespace index
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = geometry::srs::spheroid<double>,
+ typename CalculationType = void
+>
+struct geographic
+ : spherical<CalculationType>
+{
+ typedef geographic_tag cs_tag;
+
+ typedef geometry::strategy::envelope::geographic_segment
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ > envelope_segment_strategy_type;
+
+ inline envelope_segment_strategy_type get_envelope_segment_strategy() const
+ {
+ return envelope_segment_strategy_type(m_spheroid);
+ }
+
+ typedef geometry::strategy::expand::geographic_segment
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ > expand_segment_strategy_type;
+
+ inline expand_segment_strategy_type get_expand_segment_strategy() const
+ {
+ return expand_segment_strategy_type(m_spheroid);
+ }
+
+ // used in equals(Seg, Seg) but only to get_point_in_point_strategy()
+ typedef geometry::strategy::intersection::geographic_segments
+ <
+ FormulaPolicy,
+ // If index::geographic formula is derived from intersection::geographic_segments
+ // formula with different Order this may cause an inconsistency
+ strategy::default_order<FormulaPolicy>::value,
+ Spheroid,
+ CalculationType
+ > relate_segment_segment_strategy_type;
+
+ inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy() const
+ {
+ return relate_segment_segment_strategy_type(m_spheroid);
+ }
+
+ typedef geometry::strategy::distance::geographic
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ > comparable_distance_point_point_strategy_type;
+
+ inline comparable_distance_point_point_strategy_type get_comparable_distance_point_point_strategy() const
+ {
+ return comparable_distance_point_point_strategy_type(m_spheroid);
+ }
+
+ typedef geometry::strategy::distance::geographic_cross_track_point_box
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ > comparable_distance_point_box_strategy_type;
+
+ inline comparable_distance_point_box_strategy_type get_comparable_distance_point_box_strategy() const
+ {
+ return comparable_distance_point_box_strategy_type(m_spheroid);
+ }
+
+ typedef geometry::strategy::distance::geographic_cross_track
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ > comparable_distance_point_segment_strategy_type;
+
+ inline comparable_distance_point_segment_strategy_type get_comparable_distance_point_segment_strategy() const
+ {
+ return comparable_distance_point_segment_strategy_type(m_spheroid);
+ }
+
+ typedef geometry::strategy::distance::geographic_segment_box
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ > comparable_distance_segment_box_strategy_type;
+
+ inline comparable_distance_segment_box_strategy_type get_comparable_distance_segment_box_strategy() const
+ {
+ return comparable_distance_segment_box_strategy_type(m_spheroid);
+ }
+
+ geographic()
+ : m_spheroid()
+ {}
+
+ explicit geographic(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+public:
+ Spheroid m_spheroid;
+};
+
+
+namespace services
+{
+
+template <typename Geometry>
+struct default_strategy<Geometry, geographic_tag>
+{
+ typedef geographic<> type;
+};
+
+
+// within and relate (MPt, Mls/MPoly)
+template <typename Point1, typename Point2, typename Formula, typename Spheroid, typename CalculationType>
+struct from_strategy<within::geographic_winding<Point1, Point2, Formula, Spheroid, CalculationType> >
+{
+ typedef strategy::index::geographic<Formula, Spheroid, CalculationType> type;
+
+ static inline type get(within::geographic_winding<Point1, Point2, Formula, Spheroid, CalculationType> const& strategy)
+ {
+ return type(strategy.model());
+ }
+};
+
+// distance (MPt, MPt)
+template <typename Formula, typename Spheroid, typename CalculationType>
+struct from_strategy<distance::geographic<Formula, Spheroid, CalculationType> >
+{
+ typedef strategy::index::geographic<Formula, Spheroid, CalculationType> type;
+
+ static inline type get(distance::geographic<Formula, Spheroid, CalculationType> const& strategy)
+ {
+ return type(strategy.model());
+ }
+};
+template <typename Spheroid, typename CalculationType>
+struct from_strategy<distance::andoyer<Spheroid, CalculationType> >
+{
+ typedef strategy::index::geographic<strategy::andoyer, Spheroid, CalculationType> type;
+
+ static inline type get(distance::andoyer<Spheroid, CalculationType> const& strategy)
+ {
+ return type(strategy.model());
+ }
+};
+template <typename Spheroid, typename CalculationType>
+struct from_strategy<distance::thomas<Spheroid, CalculationType> >
+{
+ typedef strategy::index::geographic<strategy::thomas, Spheroid, CalculationType> type;
+
+ static inline type get(distance::thomas<Spheroid, CalculationType> const& strategy)
+ {
+ return type(strategy.model());
+ }
+};
+template <typename Spheroid, typename CalculationType>
+struct from_strategy<distance::vincenty<Spheroid, CalculationType> >
+{
+ typedef strategy::index::geographic<strategy::vincenty, Spheroid, CalculationType> type;
+
+ static inline type get(distance::vincenty<Spheroid, CalculationType> const& strategy)
+ {
+ return type(strategy.model());
+ }
+};
+
+// distance (MPt, Linear/Areal)
+template <typename Formula, typename Spheroid, typename CalculationType>
+struct from_strategy<distance::geographic_cross_track<Formula, Spheroid, CalculationType> >
+{
+ typedef strategy::index::geographic<Formula, Spheroid, CalculationType> type;
+
+ static inline type get(distance::geographic_cross_track<Formula, Spheroid, CalculationType> const& strategy)
+ {
+ return type(strategy.model());
+ }
+};
+
+
+} // namespace services
+
+
+}}}} // namespace boost::geometry::strategy::index
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INDEX_HPP
diff --git a/boost/geometry/strategies/geographic/intersection.hpp b/boost/geometry/strategies/geographic/intersection.hpp
index 37f79e5895..1d69933502 100644
--- a/boost/geometry/strategies/geographic/intersection.hpp
+++ b/boost/geometry/strategies/geographic/intersection.hpp
@@ -74,6 +74,8 @@ template
>
struct geographic_segments
{
+ typedef geographic_tag cs_tag;
+
typedef side::geographic
<
FormulaPolicy, Spheroid, CalculationType
@@ -193,6 +195,9 @@ struct geographic_segments
}
typedef covered_by::spherical_point_box disjoint_point_box_strategy_type;
+ typedef covered_by::spherical_point_box covered_by_point_box_strategy_type;
+ typedef within::spherical_point_box within_point_box_strategy_type;
+ typedef envelope::spherical_box envelope_box_strategy_type;
typedef expand::spherical_box expand_box_strategy_type;
enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
@@ -494,7 +499,6 @@ private:
}
// 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);
diff --git a/boost/geometry/strategies/geographic/point_in_poly_winding.hpp b/boost/geometry/strategies/geographic/point_in_poly_winding.hpp
index 95a1961474..fe45f8db7a 100644
--- a/boost/geometry/strategies/geographic/point_in_poly_winding.hpp
+++ b/boost/geometry/strategies/geographic/point_in_poly_winding.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2017 Oracle and/or its affiliates.
+// Copyright (c) 2017, 2019 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,
@@ -38,8 +38,8 @@ namespace strategy { namespace within
*/
template
<
- typename Point,
- typename PointOfSegment = Point,
+ typename Point = void, // for backward compatibility
+ typename PointOfSegment = Point, // for backward compatibility
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
@@ -47,16 +47,12 @@ template
class geographic_winding
: public within::detail::spherical_winding_base
<
- Point,
- PointOfSegment,
side::geographic<FormulaPolicy, Spheroid, CalculationType>,
CalculationType
>
{
typedef within::detail::spherical_winding_base
<
- Point,
- PointOfSegment,
side::geographic<FormulaPolicy, Spheroid, CalculationType>,
CalculationType
> base_t;
@@ -68,6 +64,11 @@ public:
explicit geographic_winding(Spheroid const& model)
: base_t(model)
{}
+
+ Spheroid const& model() const
+ {
+ return base_t::m_side_strategy.model();
+ }
};
diff --git a/boost/geometry/strategies/geographic/side.hpp b/boost/geometry/strategies/geographic/side.hpp
index e22718f32b..1a9648e74c 100644
--- a/boost/geometry/strategies/geographic/side.hpp
+++ b/boost/geometry/strategies/geographic/side.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2018.
-// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2019.
+// Modifications copyright (c) 2014-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -65,6 +65,8 @@ template
class geographic
{
public:
+ typedef geographic_tag cs_tag;
+
typedef strategy::envelope::geographic
<
FormulaPolicy,
@@ -123,6 +125,11 @@ public:
return formula::azimuth_side_value(a1p, a12);
}
+ Spheroid const& model() const
+ {
+ return m_model;
+ }
+
private:
template <typename ResultType,
typename InverseFormulaType,
diff --git a/boost/geometry/strategies/index.hpp b/boost/geometry/strategies/index.hpp
new file mode 100644
index 0000000000..049b29c5bc
--- /dev/null
+++ b/boost/geometry/strategies/index.hpp
@@ -0,0 +1,71 @@
+// Boost.Geometry Index
+//
+// R-tree strategies
+//
+// Copyright (c) 2019, 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_INDEX_HPP
+#define BOOST_GEOMETRY_STRATEGIES_INDEX_HPP
+
+
+#include <boost/geometry/core/cs.hpp>
+
+#include <boost/geometry/strategies/default_strategy.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy { namespace index
+{
+
+namespace services
+{
+
+template
+<
+ typename Geometry,
+ typename CSTag = typename geometry::cs_tag<Geometry>::type
+>
+struct default_strategy
+{
+ /*BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THESE_TYPES
+ , (types<Geometry>)
+ );*/
+
+ typedef geometry::default_strategy type;
+};
+
+
+// TEMP
+// Utility to get index strategy from other strategy
+// In the final version this utility will probably replaced with some other mechanism
+// The issue is cross-dependencies between strategies
+template <typename Strategy>
+struct from_strategy
+{
+ /*BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THESE_TYPES
+ , (types<Strategy>)
+ );*/
+
+ typedef geometry::default_strategy type;
+
+ static inline type get(Strategy const&)
+ {
+ return type();
+ }
+};
+
+
+} // namespace services
+
+
+}}}} // namespace boost::geometry::strategy::index
+
+#endif // BOOST_GEOMETRY_STRATEGIES_INDEX_HPP
diff --git a/boost/geometry/strategies/spherical/compare.hpp b/boost/geometry/strategies/spherical/compare.hpp
index bf28fe75a8..67acdcf6df 100644
--- a/boost/geometry/strategies/spherical/compare.hpp
+++ b/boost/geometry/strategies/spherical/compare.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017, 2018.
-// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017, 2018, 2019.
+// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -70,9 +70,9 @@ template
struct spherical_latitude
{
typedef typename geometry::coordinate_type<Point1>::type coordinate1_type;
- typedef typename geometry::coordinate_system<Point1>::type::units units1_type;
+ typedef typename geometry::detail::cs_angular_units<Point1>::type units1_type;
typedef typename geometry::coordinate_type<Point2>::type coordinate2_type;
- typedef typename geometry::coordinate_system<Point2>::type::units units2_type;
+ typedef typename geometry::detail::cs_angular_units<Point2>::type units2_type;
typedef typename boost::is_same<units1_type, units2_type>::type same_units_type;
template <typename T1, typename T2>
@@ -136,9 +136,9 @@ template
struct spherical_longitude
{
typedef typename geometry::coordinate_type<Point1>::type coordinate1_type;
- typedef typename geometry::coordinate_system<Point1>::type::units units1_type;
+ typedef typename geometry::detail::cs_angular_units<Point1>::type units1_type;
typedef typename geometry::coordinate_type<Point2>::type coordinate2_type;
- typedef typename geometry::coordinate_system<Point2>::type::units units2_type;
+ typedef typename geometry::detail::cs_angular_units<Point2>::type units2_type;
typedef typename boost::is_same<units1_type, units2_type>::type same_units_type;
typedef typename boost::mpl::if_<same_units_type, units1_type, geometry::radian>::type units_type;
@@ -284,6 +284,16 @@ template <typename ComparePolicy, typename Point1, typename Point2, int Dimensio
struct default_strategy
<
ComparePolicy, Point1, Point2, Dimension,
+ spherical_tag, spherical_tag
+ >
+{
+ typedef compare::spherical<ComparePolicy, Dimension> type;
+};
+
+template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
+struct default_strategy
+ <
+ ComparePolicy, Point1, Point2, Dimension,
spherical_polar_tag, spherical_polar_tag
>
{
diff --git a/boost/geometry/strategies/spherical/disjoint_segment_box.hpp b/boost/geometry/strategies/spherical/disjoint_segment_box.hpp
index 9c6711dea6..29b6bdaf59 100644
--- a/boost/geometry/strategies/spherical/disjoint_segment_box.hpp
+++ b/boost/geometry/strategies/spherical/disjoint_segment_box.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2017-2018 Oracle and/or its affiliates.
+// Copyright (c) 2017-2019 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
@@ -46,22 +46,11 @@ namespace boost { namespace geometry { namespace strategy { namespace disjoint
// other strategies that are used are intersection and covered_by strategies.
struct segment_box_spherical
{
- template <typename Segment, typename Box>
- struct point_in_geometry_strategy
- : services::default_strategy
- <
- typename point_type<Segment>::type,
- Box
- >
- {};
+ typedef covered_by::spherical_point_box disjoint_point_box_strategy_type;
- template <typename Segment, typename Box>
- static inline typename point_in_geometry_strategy<Segment, Box>::type
- get_point_in_geometry_strategy()
+ static inline disjoint_point_box_strategy_type get_disjoint_point_box_strategy()
{
- typedef typename point_in_geometry_strategy<Segment, Box>::type strategy_type;
-
- return strategy_type();
+ return disjoint_point_box_strategy_type();
}
template <typename Segment, typename Box>
diff --git a/boost/geometry/strategies/spherical/distance_cross_track.hpp b/boost/geometry/strategies/spherical/distance_cross_track.hpp
index 280bf76b43..439de0d03c 100644
--- a/boost/geometry/strategies/spherical/distance_cross_track.hpp
+++ b/boost/geometry/strategies/spherical/distance_cross_track.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2018.
-// Modifications copyright (c) 2014-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2019.
+// Modifications copyright (c) 2014-2019, 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
@@ -34,6 +34,7 @@
#include <boost/geometry/strategies/concepts/distance_concept.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
+#include <boost/geometry/strategies/spherical/intersection.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
@@ -332,6 +333,26 @@ class cross_track
public :
typedef within::spherical_point_point equals_point_point_strategy_type;
+ typedef intersection::spherical_segments
+ <
+ CalculationType
+ > relate_segment_segment_strategy_type;
+
+ static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy()
+ {
+ return relate_segment_segment_strategy_type();
+ }
+
+ typedef within::spherical_winding
+ <
+ void, void, CalculationType
+ > point_in_geometry_strategy_type;
+
+ static inline point_in_geometry_strategy_type get_point_in_geometry_strategy()
+ {
+ return point_in_geometry_strategy_type();
+ }
+
template <typename Point, typename PointOfSegment>
struct return_type
: promote_floating_point
@@ -513,6 +534,26 @@ class cross_track
public :
typedef within::spherical_point_point equals_point_point_strategy_type;
+ typedef intersection::spherical_segments
+ <
+ CalculationType
+ > relate_segment_segment_strategy_type;
+
+ static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy()
+ {
+ return relate_segment_segment_strategy_type();
+ }
+
+ typedef within::spherical_winding
+ <
+ void, void, CalculationType
+ > point_in_geometry_strategy_type;
+
+ static inline point_in_geometry_strategy_type get_point_in_geometry_strategy()
+ {
+ return point_in_geometry_strategy_type();
+ }
+
template <typename Point, typename PointOfSegment>
struct return_type
: promote_floating_point
diff --git a/boost/geometry/strategies/spherical/distance_segment_box.hpp b/boost/geometry/strategies/spherical/distance_segment_box.hpp
index bb622ec52d..addc2b9e14 100644
--- a/boost/geometry/strategies/spherical/distance_segment_box.hpp
+++ b/boost/geometry/strategies/spherical/distance_segment_box.hpp
@@ -19,6 +19,7 @@
#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp> // spherical
+#include <boost/geometry/strategies/spherical/ssf.hpp>
namespace boost { namespace geometry
{
@@ -58,14 +59,28 @@ struct generic_segment_box
{
ReturnType result;
typename LessEqual::other less_equal;
- typedef geometry::model::segment<SegmentPoint> Segment;
- typedef typename cs_tag<Segment>::type segment_cs_type;
+ typedef geometry::model::segment<SegmentPoint> segment_type;
+ // if cs_tag is spherical_tag check segment's cs_tag with spherical_equatorial_tag as default
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_same<typename SegmentBoxStrategy::cs_tag, spherical_tag>::value,
+ typename boost::mpl::if_c
+ <
+ boost::is_same
+ <
+ typename geometry::cs_tag<segment_type>::type,
+ spherical_polar_tag
+ >::value,
+ spherical_polar_tag, spherical_equatorial_tag
+ >::type,
+ typename SegmentBoxStrategy::cs_tag
+ >::type cs_tag;
typedef geometry::detail::disjoint::
- disjoint_segment_box_sphere_or_spheroid<segment_cs_type>
+ disjoint_segment_box_sphere_or_spheroid<cs_tag>
disjoint_sb;
typedef typename disjoint_sb::disjoint_info disjoint_info_type;
- Segment seg(p0, p1);
+ segment_type seg(p0, p1);
geometry::model::box<BoxPoint> input_box;
geometry::set_from_radian<geometry::min_corner, 0>
@@ -120,7 +135,7 @@ struct generic_segment_box
CT vertex_lon = geometry::formula::vertex_longitude
<
CT,
- segment_cs_type
+ cs_tag
>::apply(lon1, lat1, lon2, lat2,
vertex_lat, alp1, az_strategy);
@@ -196,6 +211,8 @@ struct spherical_segment_box
>
{};
+ typedef spherical_tag cs_tag;
+
// strategy getters
// point-point strategy getters
@@ -219,6 +236,25 @@ struct spherical_segment_box
return typename distance_ps_strategy::type();
}
+ struct distance_pb_strategy
+ {
+ typedef cross_track_point_box<CalculationType, Strategy> type;
+ };
+
+ inline typename distance_pb_strategy::type get_distance_pb_strategy() const
+ {
+ return typename distance_pb_strategy::type();
+ }
+
+ // TODO: why is the Radius not propagated above?
+
+ typedef side::spherical_side_formula<CalculationType> side_strategy_type;
+
+ static inline side_strategy_type get_side_strategy()
+ {
+ return side_strategy_type();
+ }
+
typedef within::spherical_point_point equals_point_point_strategy_type;
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
diff --git a/boost/geometry/strategies/spherical/envelope_box.hpp b/boost/geometry/strategies/spherical/envelope_box.hpp
index 0a9436d123..b7fa2ebea9 100644
--- a/boost/geometry/strategies/spherical/envelope_box.hpp
+++ b/boost/geometry/strategies/spherical/envelope_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-2018.
-// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015-2019.
+// Modifications copyright (c) 2015-2019, 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
@@ -18,20 +18,8 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_BOX_HPP
-#include <cstddef>
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/coordinate_dimension.hpp>
-#include <boost/geometry/core/coordinate_system.hpp>
-#include <boost/geometry/core/tags.hpp>
-
-#include <boost/geometry/views/detail/indexed_point_view.hpp>
-
-#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
-#include <boost/geometry/algorithms/detail/normalize.hpp>
-#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
-
-#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+#include <boost/geometry/strategies/spherical/expand_box.hpp>
#include <boost/geometry/strategies/envelope.hpp>
@@ -39,71 +27,18 @@
namespace boost { namespace geometry
{
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace envelope
-{
-
-
-template
-<
- std::size_t Index,
- std::size_t DimensionCount
->
-struct envelope_indexed_box_on_spheroid
-{
- template <typename BoxIn, typename BoxOut>
- static inline void apply(BoxIn const& box_in, BoxOut& mbr)
- {
- // transform() does not work with boxes of dimension higher
- // than 2; to account for such boxes we transform the min/max
- // points of the boxes using the indexed_point_view
- detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
- detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
-
- // first transform the units
- transform_units(box_in_corner, mbr_corner);
-
- // now transform the remaining coordinates
- detail::conversion::point_to_point
- <
- detail::indexed_point_view<BoxIn const, Index>,
- detail::indexed_point_view<BoxOut, Index>,
- 2,
- DimensionCount
- >::apply(box_in_corner, mbr_corner);
- }
-};
-
-
-}} // namespace detail::envelope
-#endif // DOXYGEN_NO_DETAIL
-
-
namespace strategy { namespace envelope
{
struct spherical_box
+ : geometry::detail::envelope::envelope_box_on_spheroid
{
- template <typename BoxIn, typename BoxOut>
- static inline void apply(BoxIn const& box_in, BoxOut& mbr)
+ typedef strategy::expand::spherical_box box_expand_strategy_type;
+
+ static inline box_expand_strategy_type get_box_expand_strategy()
{
- BoxIn box_in_normalized = box_in;
-
- if (!is_inverse_spheroidal_coordinates(box_in))
- {
- strategy::normalize::spherical_box::apply(box_in, box_in_normalized);
- }
-
- geometry::detail::envelope::envelope_indexed_box_on_spheroid
- <
- min_corner, dimension<BoxIn>::value
- >::apply(box_in_normalized, mbr);
-
- geometry::detail::envelope::envelope_indexed_box_on_spheroid
- <
- max_corner, dimension<BoxIn>::value
- >::apply(box_in_normalized, mbr);
+ return box_expand_strategy_type();
}
};
diff --git a/boost/geometry/strategies/spherical/expand_box.hpp b/boost/geometry/strategies/spherical/expand_box.hpp
index e3801861b2..e4bfafadd5 100644
--- a/boost/geometry/strategies/spherical/expand_box.hpp
+++ b/boost/geometry/strategies/spherical/expand_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// This file was modified by Oracle on 2015, 2016, 2017, 2018.
-// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016, 2017, 2018, 2019.
+// Modifications copyright (c) 2015-2019, 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
@@ -19,18 +19,95 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_BOX_HPP
-#include <cstddef>
#include <algorithm>
+#include <cstddef>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/algorithms/detail/envelope/box.hpp>
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
+#include <boost/geometry/algorithms/detail/normalize.hpp>
+#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+
+#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/strategies/expand.hpp>
-#include <boost/geometry/strategies/spherical/envelope_box.hpp>
+
+#include <boost/geometry/views/detail/indexed_point_view.hpp>
namespace boost { namespace geometry
{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope
+{
+
+template
+<
+ std::size_t Index,
+ std::size_t DimensionCount
+>
+struct envelope_indexed_box_on_spheroid
+{
+ template <typename BoxIn, typename BoxOut>
+ static inline void apply(BoxIn const& box_in, BoxOut& mbr)
+ {
+ // transform() does not work with boxes of dimension higher
+ // than 2; to account for such boxes we transform the min/max
+ // points of the boxes using the indexed_point_view
+ detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
+ detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
+
+ // first transform the units
+ transform_units(box_in_corner, mbr_corner);
+
+ // now transform the remaining coordinates
+ detail::conversion::point_to_point
+ <
+ detail::indexed_point_view<BoxIn const, Index>,
+ detail::indexed_point_view<BoxOut, Index>,
+ 2,
+ DimensionCount
+ >::apply(box_in_corner, mbr_corner);
+ }
+};
+
+struct envelope_box_on_spheroid
+{
+ template <typename BoxIn, typename BoxOut>
+ static inline void apply(BoxIn const& box_in, BoxOut& mbr)
+ {
+ // BoxIn can be non-mutable
+ typename helper_geometry<BoxIn>::type box_in_normalized;
+ geometry::convert(box_in, box_in_normalized);
+
+ if (! is_inverse_spheroidal_coordinates(box_in))
+ {
+ strategy::normalize::spherical_box::apply(box_in, box_in_normalized);
+ }
+
+ geometry::detail::envelope::envelope_indexed_box_on_spheroid
+ <
+ min_corner, dimension<BoxIn>::value
+ >::apply(box_in_normalized, mbr);
+
+ geometry::detail::envelope::envelope_indexed_box_on_spheroid
+ <
+ max_corner, dimension<BoxIn>::value
+ >::apply(box_in_normalized, mbr);
+ }
+};
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+
namespace strategy { namespace expand
{
@@ -45,8 +122,8 @@ struct box_on_spheroid
{
// normalize both boxes and convert box-in to be of type of box-out
BoxOut mbrs[2];
- strategy::envelope::spherical_box::apply(box_in, mbrs[0]);
- strategy::envelope::spherical_box::apply(box_out, mbrs[1]);
+ geometry::detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]);
+ geometry::detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]);
// compute the envelope of the two boxes
geometry::detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out);
diff --git a/boost/geometry/strategies/spherical/index.hpp b/boost/geometry/strategies/spherical/index.hpp
new file mode 100644
index 0000000000..cd1734e944
--- /dev/null
+++ b/boost/geometry/strategies/spherical/index.hpp
@@ -0,0 +1,198 @@
+// Boost.Geometry Index
+//
+// R-tree strategies
+//
+// Copyright (c) 2019, 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_SPHERICAL_INDEX_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_INDEX_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/distance_segment_box.hpp>
+#include <boost/geometry/strategies/spherical/envelope_box.hpp>
+#include <boost/geometry/strategies/spherical/envelope_point.hpp>
+#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
+#include <boost/geometry/strategies/spherical/expand_box.hpp>
+#include <boost/geometry/strategies/spherical/expand_point.hpp>
+#include <boost/geometry/strategies/spherical/expand_segment.hpp>
+#include <boost/geometry/strategies/spherical/intersection.hpp>
+#include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp>
+
+#include <boost/geometry/strategies/index.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy { namespace index
+{
+
+template
+<
+ typename CalculationType = void
+>
+struct spherical
+{
+ typedef spherical_tag cs_tag;
+
+ typedef geometry::strategy::envelope::spherical_point envelope_point_strategy_type;
+ typedef geometry::strategy::envelope::spherical_box envelope_box_strategy_type;
+ typedef geometry::strategy::envelope::spherical_segment
+ <
+ CalculationType
+ > envelope_segment_strategy_type;
+
+ static inline envelope_segment_strategy_type get_envelope_segment_strategy()
+ {
+ return envelope_segment_strategy_type();
+ }
+
+ typedef geometry::strategy::expand::spherical_point expand_point_strategy_type;
+ typedef geometry::strategy::expand::spherical_box expand_box_strategy_type;
+ typedef geometry::strategy::expand::spherical_segment
+ <
+ CalculationType
+ > expand_segment_strategy_type;
+
+ static inline expand_segment_strategy_type get_expand_segment_strategy()
+ {
+ return expand_segment_strategy_type();
+ }
+
+ typedef geometry::strategy::covered_by::spherical_point_box covered_by_point_box_strategy_type;
+ typedef geometry::strategy::covered_by::spherical_box_box covered_by_box_box_strategy_type;
+ typedef geometry::strategy::within::spherical_point_point within_point_point_strategy_type;
+ //typedef geometry::strategy::within::spherical_point_box within_point_box_strategy_type;
+ //typedef geometry::strategy::within::spherical_box_box within_box_box_strategy_type;
+
+ // used in equals(Seg, Seg) but only to get_point_in_point_strategy()
+ typedef geometry::strategy::intersection::spherical_segments
+ <
+ CalculationType
+ > relate_segment_segment_strategy_type;
+
+ static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy()
+ {
+ return relate_segment_segment_strategy_type();
+ }
+
+ // used in intersection_content
+ typedef geometry::strategy::disjoint::spherical_box_box disjoint_box_box_strategy_type;
+
+ typedef geometry::strategy::distance::comparable::haversine
+ <
+ double,
+ CalculationType
+ > comparable_distance_point_point_strategy_type;
+
+ static inline comparable_distance_point_point_strategy_type get_comparable_distance_point_point_strategy()
+ {
+ return comparable_distance_point_point_strategy_type();
+ }
+
+ // TODO: Comparable version should be possible
+ typedef geometry::strategy::distance::cross_track_point_box
+ <
+ CalculationType,
+ geometry::strategy::distance::haversine<double, CalculationType>
+ > comparable_distance_point_box_strategy_type;
+
+ static inline comparable_distance_point_box_strategy_type get_comparable_distance_point_box_strategy()
+ {
+ return comparable_distance_point_box_strategy_type();
+ }
+
+ // TODO: Radius is not needed in comparable strategy
+ typedef geometry::strategy::distance::comparable::cross_track
+ <
+ CalculationType,
+ geometry::strategy::distance::comparable::haversine<double, CalculationType>
+ > comparable_distance_point_segment_strategy_type;
+
+ static inline comparable_distance_point_segment_strategy_type get_comparable_distance_point_segment_strategy()
+ {
+ return comparable_distance_point_segment_strategy_type();
+ }
+
+ // comparable?
+ typedef geometry::strategy::distance::spherical_segment_box
+ <
+ CalculationType,
+ geometry::strategy::distance::haversine<double, CalculationType>
+ > comparable_distance_segment_box_strategy_type;
+
+ static inline comparable_distance_segment_box_strategy_type get_comparable_distance_segment_box_strategy()
+ {
+ return comparable_distance_segment_box_strategy_type();
+ }
+};
+
+
+namespace services
+{
+
+template <typename Geometry>
+struct default_strategy<Geometry, spherical_tag>
+{
+ typedef spherical<> type;
+};
+
+template <typename Geometry>
+struct default_strategy<Geometry, spherical_polar_tag>
+{
+ typedef spherical<> type;
+};
+
+template <typename Geometry>
+struct default_strategy<Geometry, spherical_equatorial_tag>
+{
+ typedef spherical<> type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct from_strategy<within::spherical_winding<Point1, Point2, CalculationType> >
+{
+ typedef strategy::index::spherical<CalculationType> type;
+
+ static inline type get(within::spherical_winding<Point1, Point2, CalculationType> const&)
+ {
+ return type();
+ }
+};
+
+// distance (MPt, MPt)
+template <typename RadiusType, typename CalculationType>
+struct from_strategy<distance::comparable::haversine<RadiusType, CalculationType> >
+{
+ typedef strategy::index::spherical<CalculationType> type;
+
+ static inline type get(distance::comparable::haversine<RadiusType, CalculationType> const&)
+ {
+ return type();
+ }
+};
+
+// distance (MPt, Linear/Areal)
+template <typename CalculationType, typename PPStrategy>
+struct from_strategy<distance::comparable::cross_track<CalculationType, PPStrategy> >
+{
+ typedef strategy::index::spherical<CalculationType> type;
+
+ static inline type get(distance::comparable::cross_track<CalculationType, PPStrategy> const&)
+ {
+ return type();
+ }
+};
+
+
+} // namespace services
+
+
+}}}} // namespace boost::geometry::strategy::index
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_INDEX_HPP
diff --git a/boost/geometry/strategies/spherical/intersection.hpp b/boost/geometry/strategies/spherical/intersection.hpp
index 4cf4fca113..e0d807a968 100644
--- a/boost/geometry/strategies/spherical/intersection.hpp
+++ b/boost/geometry/strategies/spherical/intersection.hpp
@@ -90,6 +90,8 @@ template
>
struct ecef_segments
{
+ typedef spherical_tag cs_tag;
+
typedef side::spherical_side_formula<CalculationType> side_strategy_type;
static inline side_strategy_type get_side_strategy()
@@ -198,6 +200,9 @@ struct ecef_segments
}
typedef covered_by::spherical_point_box disjoint_point_box_strategy_type;
+ typedef covered_by::spherical_point_box covered_by_point_box_strategy_type;
+ typedef within::spherical_point_box within_point_box_strategy_type;
+ typedef envelope::spherical_box envelope_box_strategy_type;
typedef expand::spherical_box expand_box_strategy_type;
enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
diff --git a/boost/geometry/strategies/spherical/point_in_point.hpp b/boost/geometry/strategies/spherical/point_in_point.hpp
index 372e9cfaca..b6e6973bda 100644
--- a/boost/geometry/strategies/spherical/point_in_point.hpp
+++ b/boost/geometry/strategies/spherical/point_in_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, 2017, 2018.
-// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019.
+// Modifications copyright (c) 2013-2019, 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
@@ -56,6 +56,9 @@ namespace detail { namespace within
class point_point_on_spheroid
{
+public:
+ typedef spherical_tag cs_tag;
+
private:
template <typename Point1, typename Point2, bool SameUnits>
struct are_same_points
diff --git a/boost/geometry/strategies/spherical/point_in_poly_winding.hpp b/boost/geometry/strategies/spherical/point_in_poly_winding.hpp
index c283b53335..1917869ed1 100644
--- a/boost/geometry/strategies/spherical/point_in_poly_winding.hpp
+++ b/boost/geometry/strategies/spherical/point_in_poly_winding.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018.
-// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018, 2019.
+// Modifications copyright (c) 2013-2019 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
@@ -46,28 +46,19 @@ namespace strategy { namespace within
namespace detail
{
-template
-<
- typename Point,
- typename PointOfSegment = Point,
- typename SideStrategy = typename strategy::side::services::default_strategy
- <
- typename cs_tag<Point>::type
- >::type,
- typename CalculationType = void
->
+template <typename SideStrategy, typename CalculationType>
class spherical_winding_base
{
- typedef typename select_calculation_type
- <
- Point,
- PointOfSegment,
- CalculationType
- >::type calculation_type;
+ template <typename Point, typename PointOfSegment>
+ struct calculation_type
+ : select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >
+ {};
- typedef typename geometry::detail::cs_angular_units<Point>::type units_t;
- typedef math::detail::constants_on_spheroid<calculation_type, units_t> constants;
-
/*! subclass to keep state */
class counter
{
@@ -128,6 +119,17 @@ class spherical_winding_base
};
public:
+ typedef typename SideStrategy::cs_tag cs_tag;
+
+ typedef SideStrategy side_strategy_type;
+
+ inline side_strategy_type get_side_strategy() const
+ {
+ return m_side_strategy;
+ }
+
+ typedef expand::spherical_point expand_point_strategy_type;
+
typedef typename SideStrategy::envelope_strategy_type envelope_strategy_type;
inline envelope_strategy_type get_envelope_strategy() const
@@ -165,14 +167,17 @@ public:
{}
// Typedefs and static methods to fulfill the concept
- typedef Point point_type;
- typedef PointOfSegment segment_point_type;
typedef counter state_type;
+ template <typename Point, typename PointOfSegment>
inline bool apply(Point const& point,
PointOfSegment const& s1, PointOfSegment const& s2,
counter& state) const
{
+ typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
+ typedef typename geometry::detail::cs_angular_units<Point>::type units_t;
+ typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
+
bool eq1 = false;
bool eq2 = false;
bool s_antipodal = false;
@@ -196,9 +201,9 @@ public:
}
else
{
- calculation_type const pi = constants::half_period();
- calculation_type const s1_lat = get<1>(s1);
- calculation_type const s2_lat = get<1>(s2);
+ calc_t const pi = constants::half_period();
+ calc_t const s1_lat = get<1>(s1);
+ calc_t const s2_lat = get<1>(s2);
side = math::sign(ci.count)
* (pi - s1_lat - s2_lat <= pi // segment goes through north pole
@@ -250,8 +255,8 @@ public:
return state.code();
}
-private:
-
+protected:
+ template <typename Point, typename PointOfSegment>
static inline count_info check_segment(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
@@ -266,6 +271,7 @@ private:
return calculate_count(point, seg1, seg2, eq1, eq2, s_antipodal);
}
+ template <typename Point, typename PointOfSegment>
static inline int check_touch(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
@@ -274,39 +280,43 @@ private:
bool& eq2,
bool& s_antipodal)
{
- calculation_type const c0 = 0;
- calculation_type const c2 = 2;
- calculation_type const pi = constants::half_period();
- calculation_type const half_pi = pi / c2;
-
- calculation_type const p_lon = get<0>(point);
- calculation_type const s1_lon = get<0>(seg1);
- calculation_type const s2_lon = get<0>(seg2);
- calculation_type const p_lat = get<1>(point);
- calculation_type const s1_lat = get<1>(seg1);
- calculation_type const s2_lat = get<1>(seg2);
+ typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
+ typedef typename geometry::detail::cs_angular_units<Point>::type units_t;
+ typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
+
+ calc_t const c0 = 0;
+ calc_t const c2 = 2;
+ calc_t const pi = constants::half_period();
+ calc_t const half_pi = pi / c2;
+
+ calc_t const p_lon = get<0>(point);
+ calc_t const s1_lon = get<0>(seg1);
+ calc_t const s2_lon = get<0>(seg2);
+ calc_t const p_lat = get<1>(point);
+ calc_t const s1_lat = get<1>(seg1);
+ calc_t const s2_lat = get<1>(seg2);
// NOTE: lat in {-90, 90} and arbitrary lon
// it doesn't matter what lon it is if it's a pole
// so e.g. if one of the segment endpoints is a pole
// then only the other lon matters
- bool eq1_strict = longitudes_equal(s1_lon, p_lon);
- bool eq2_strict = longitudes_equal(s2_lon, p_lon);
+ bool eq1_strict = longitudes_equal<units_t>(s1_lon, p_lon);
+ bool eq2_strict = longitudes_equal<units_t>(s2_lon, p_lon);
bool eq1_anti = false;
bool eq2_anti = false;
- calculation_type const anti_p_lon = p_lon + (p_lon <= c0 ? pi : -pi);
+ calc_t const anti_p_lon = p_lon + (p_lon <= c0 ? pi : -pi);
eq1 = eq1_strict // lon strictly equal to s1
- || (eq1_anti = longitudes_equal(s1_lon, anti_p_lon)) // anti-lon strictly equal to s1
+ || (eq1_anti = longitudes_equal<units_t>(s1_lon, anti_p_lon)) // anti-lon strictly equal to s1
|| math::equals(math::abs(s1_lat), half_pi); // s1 is pole
eq2 = eq2_strict // lon strictly equal to s2
- || (eq2_anti = longitudes_equal(s2_lon, anti_p_lon)) // anti-lon strictly equal to s2
+ || (eq2_anti = longitudes_equal<units_t>(s2_lon, anti_p_lon)) // anti-lon strictly equal to s2
|| math::equals(math::abs(s2_lat), half_pi); // s2 is pole
// segment overlapping pole
- calculation_type const s_lon_diff = math::longitude_distance_signed<units_t>(s1_lon, s2_lon);
+ calc_t const s_lon_diff = math::longitude_distance_signed<units_t>(s1_lon, s2_lon);
s_antipodal = math::equals(s_lon_diff, pi);
if (s_antipodal)
{
@@ -371,36 +381,41 @@ private:
}
// Called if point is not aligned with a vertical segment
+ template <typename Point, typename PointOfSegment>
static inline count_info calculate_count(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
bool eq1, bool eq2, bool s_antipodal)
{
+ typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
+ typedef typename geometry::detail::cs_angular_units<Point>::type units_t;
+ typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
+
// If both segment endpoints were poles below checks wouldn't be enough
// but this means that either both are the same or that they are N/S poles
// and therefore the segment is not valid.
// If needed (eq1 && eq2 ? 0) could be returned
- calculation_type const c0 = 0;
- calculation_type const pi = constants::half_period();
+ calc_t const c0 = 0;
+ calc_t const pi = constants::half_period();
- calculation_type const p = get<0>(point);
- calculation_type const s1 = get<0>(seg1);
- calculation_type const s2 = get<0>(seg2);
+ calc_t const p = get<0>(point);
+ calc_t const s1 = get<0>(seg1);
+ calc_t const s2 = get<0>(seg2);
- calculation_type const s1_p = math::longitude_distance_signed<units_t>(s1, p);
+ calc_t const s1_p = math::longitude_distance_signed<units_t>(s1, p);
if (s_antipodal)
{
return count_info(s1_p < c0 ? -2 : 2, false); // choose W/E
}
- calculation_type const s1_s2 = math::longitude_distance_signed<units_t>(s1, s2);
+ calc_t const s1_s2 = math::longitude_distance_signed<units_t>(s1, s2);
if (eq1 || eq2) // Point on level s1 or s2
{
return count_info(s1_s2 < c0 ? -1 : 1, // choose W/E
- longitudes_equal(p + pi, (eq1 ? s1 : s2)));
+ longitudes_equal<units_t>(p + pi, (eq1 ? s1 : s2)));
}
// Point between s1 and s2
@@ -410,7 +425,7 @@ private:
return count_info(s1_s2 < c0 ? -2 : 2, false); // choose W/E
}
- calculation_type const s1_p_anti = math::longitude_distance_signed<units_t>(s1, p + pi);
+ calc_t const s1_p_anti = math::longitude_distance_signed<units_t>(s1, p + pi);
// Anti-Point between s1 and s2
if ( math::sign(s1_p_anti) == math::sign(s1_s2)
@@ -445,12 +460,13 @@ private:
// In the code below actually D = 0, so segments are nearly-vertical
// Called when the point is on the same level as one of the segment's points
// but the point is not aligned with a vertical segment
+ template <typename Point, typename PointOfSegment>
inline int side_equal(Point const& point,
PointOfSegment const& se,
count_info const& ci) const
{
typedef typename coordinate_type<PointOfSegment>::type scoord_t;
- typedef typename geometry::detail::cs_angular_units<PointOfSegment>::type units_t;
+ typedef typename geometry::detail::cs_angular_units<Point>::type units_t;
if (math::equals(get<1>(point), get<1>(se)))
{
@@ -466,11 +482,11 @@ private:
scoord_t ss20 = get<0>(se);
if (ci.count > 0)
{
- ss20 += small_angle();
+ ss20 += small_angle<scoord_t, units_t>();
}
else
{
- ss20 -= small_angle();
+ ss20 -= small_angle<scoord_t, units_t>();
}
math::normalize_longitude<units_t>(ss20);
set<0>(ss2, ss20);
@@ -480,16 +496,20 @@ private:
}
// 1 deg or pi/180 rad
- static inline calculation_type small_angle()
+ template <typename CalcT, typename Units>
+ static inline CalcT small_angle()
{
- return constants::half_period() / calculation_type(180);
- };
+ typedef math::detail::constants_on_spheroid<CalcT, Units> constants;
+
+ return constants::half_period() / CalcT(180);
+ }
- static inline bool longitudes_equal(calculation_type const& lon1, calculation_type const& lon2)
+ template <typename Units, typename CalcT>
+ static inline bool longitudes_equal(CalcT const& lon1, CalcT const& lon2)
{
return math::equals(
- math::longitude_distance_signed<units_t>(lon1, lon2),
- calculation_type(0));
+ math::longitude_distance_signed<Units>(lon1, lon2),
+ CalcT(0));
}
SideStrategy m_side_strategy;
@@ -514,15 +534,13 @@ private:
*/
template
<
- typename Point,
- typename PointOfSegment = Point,
+ typename Point = void, // for backward compatibility
+ typename PointOfSegment = Point, // for backward compatibility
typename CalculationType = void
>
class spherical_winding
: public within::detail::spherical_winding_base
<
- Point,
- PointOfSegment,
side::spherical_side_formula<CalculationType>,
CalculationType
>
@@ -539,8 +557,11 @@ struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, po
{
typedef within::detail::spherical_winding_base
<
- typename geometry::point_type<PointLike>::type,
- typename geometry::point_type<Geometry>::type
+ typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<PointLike>::type
+ >::type,
+ void
> type;
};
@@ -549,8 +570,11 @@ struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, li
{
typedef within::detail::spherical_winding_base
<
- typename geometry::point_type<PointLike>::type,
- typename geometry::point_type<Geometry>::type
+ typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<PointLike>::type
+ >::type,
+ void
> type;
};
@@ -571,8 +595,11 @@ struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, po
{
typedef within::detail::spherical_winding_base
<
- typename geometry::point_type<PointLike>::type,
- typename geometry::point_type<Geometry>::type
+ typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<PointLike>::type
+ >::type,
+ void
> type;
};
@@ -581,8 +608,11 @@ struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, li
{
typedef within::detail::spherical_winding_base
<
- typename geometry::point_type<PointLike>::type,
- typename geometry::point_type<Geometry>::type
+ typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<PointLike>::type
+ >::type,
+ void
> type;
};
diff --git a/boost/geometry/strategies/spherical/ssf.hpp b/boost/geometry/strategies/spherical/ssf.hpp
index 18c547ced8..2567cf56c2 100644
--- a/boost/geometry/strategies/spherical/ssf.hpp
+++ b/boost/geometry/strategies/spherical/ssf.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2016, 2018.
-// Modifications copyright (c) 2016-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016, 2018, 2019.
+// Modifications copyright (c) 2016-2019, 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,
@@ -85,6 +85,8 @@ class spherical_side_formula
{
public :
+ typedef spherical_tag cs_tag;
+
typedef strategy::envelope::spherical<CalculationType> envelope_strategy_type;
static inline envelope_strategy_type get_envelope_strategy()
diff --git a/boost/geometry/strategies/strategies.hpp b/boost/geometry/strategies/strategies.hpp
index 026214173f..d1c4c8cd22 100644
--- a/boost/geometry/strategies/strategies.hpp
+++ b/boost/geometry/strategies/strategies.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014-2018.
-// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2019.
+// Modifications copyright (c) 2014-2019 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
@@ -64,9 +64,17 @@
#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
#include <boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp>
#include <boost/geometry/strategies/cartesian/distance_segment_box.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_box.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_point.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_multipoint.hpp>
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
+#include <boost/geometry/strategies/cartesian/expand_box.hpp>
+#include <boost/geometry/strategies/cartesian/expand_point.hpp>
+#include <boost/geometry/strategies/cartesian/expand_segment.hpp>
+#include <boost/geometry/strategies/cartesian/index.hpp>
#include <boost/geometry/strategies/cartesian/intersection.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
+#include <boost/geometry/strategies/cartesian/point_in_point.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/point_in_poly_winding.hpp>
@@ -83,8 +91,16 @@
#include <boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp>
#include <boost/geometry/strategies/spherical/distance_segment_box.hpp>
#include <boost/geometry/strategies/spherical/compare.hpp>
+#include <boost/geometry/strategies/spherical/envelope_box.hpp>
+#include <boost/geometry/strategies/spherical/envelope_point.hpp>
+#include <boost/geometry/strategies/spherical/envelope_multipoint.hpp>
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
+#include <boost/geometry/strategies/spherical/expand_box.hpp>
+#include <boost/geometry/strategies/spherical/expand_point.hpp>
+#include <boost/geometry/strategies/spherical/expand_segment.hpp>
+#include <boost/geometry/strategies/spherical/index.hpp>
#include <boost/geometry/strategies/spherical/intersection.hpp>
+#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/spherical/line_interpolate.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
@@ -103,6 +119,8 @@
#include <boost/geometry/strategies/geographic/distance_thomas.hpp>
#include <boost/geometry/strategies/geographic/distance_vincenty.hpp>
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
+#include <boost/geometry/strategies/geographic/expand_segment.hpp>
+#include <boost/geometry/strategies/geographic/index.hpp>
#include <boost/geometry/strategies/geographic/intersection.hpp>
//#include <boost/geometry/strategies/geographic/intersection_elliptic.hpp>
#include <boost/geometry/strategies/geographic/point_in_poly_winding.hpp>
diff --git a/boost/geometry/strategies/transform/matrix_transformers.hpp b/boost/geometry/strategies/transform/matrix_transformers.hpp
index a3f3223c95..3de143501c 100644
--- a/boost/geometry/strategies/transform/matrix_transformers.hpp
+++ b/boost/geometry/strategies/transform/matrix_transformers.hpp
@@ -117,6 +117,7 @@ template <typename CalculationType>
class matrix_transformer<CalculationType, 3, 2> : public matrix_transformer<CalculationType, 2, 2>
{
typedef CalculationType ct;
+ typedef boost::qvm::mat<ct, 3, 3> matrix_type;
public :
inline matrix_transformer(
@@ -129,6 +130,10 @@ public :
m_2_0, m_2_1, m_2_2)
{}
+ inline matrix_transformer(matrix_type const& matrix)
+ : matrix_transformer<CalculationType, 2,2>(matrix)
+ {}
+
inline matrix_transformer()
: matrix_transformer<CalculationType, 2, 2>()
{}
@@ -157,6 +162,10 @@ public :
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 matrix_transformer(matrix_type const& matrix)
+ : m_matrix(matrix)
+ {}
+
inline matrix_transformer() {}
template <typename P1, typename P2>
diff --git a/boost/geometry/util/range.hpp b/boost/geometry/util/range.hpp
index 6d49e45fdd..e6acb1816a 100644
--- a/boost/geometry/util/range.hpp
+++ b/boost/geometry/util/range.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015, 2016.
-// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2016, 2019.
+// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -305,7 +305,7 @@ erase(Range & rng,
it = boost::begin(rng)
+ std::distance(boost::const_begin(rng), cit);
- return erase(rng, it);
+ return range::erase(rng, it);
}
/*!
@@ -366,7 +366,7 @@ erase(Range & rng,
last = boost::begin(rng)
+ std::distance(boost::const_begin(rng), clast);
- return erase(rng, first, last);
+ return range::erase(rng, first, last);
}
// back_inserter
diff --git a/boost/graph/adjacency_matrix.hpp b/boost/graph/adjacency_matrix.hpp
index ade7351fb8..571bc3d3d1 100644
--- a/boost/graph/adjacency_matrix.hpp
+++ b/boost/graph/adjacency_matrix.hpp
@@ -14,9 +14,9 @@
#include <boost/config.hpp>
#include <vector>
#include <memory>
+#include <iterator>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
-#include <boost/iterator.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_mutability_traits.hpp>
#include <boost/graph/graph_selectors.hpp>
@@ -499,7 +499,11 @@ namespace boost {
#if defined(BOOST_NO_STD_ALLOCATOR)
typedef std::vector<StoredEdge> Matrix;
#else
+#if defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename Allocator::template rebind<StoredEdge>::other Alloc;
+#else
+ typedef typename std::allocator_traits<Allocator>::template rebind_alloc<StoredEdge> Alloc;
+#endif
typedef std::vector<StoredEdge, Alloc> Matrix;
#endif
typedef typename Matrix::iterator MatrixIter;
diff --git a/boost/graph/astar_search.hpp b/boost/graph/astar_search.hpp
index f9f86c14c6..8201b50f17 100644
--- a/boost/graph/astar_search.hpp
+++ b/boost/graph/astar_search.hpp
@@ -430,33 +430,89 @@ namespace boost {
// Distance type is the value type of the distance map if there is one,
// otherwise the value type of the weight map.
- typedef
- typename detail::override_const_property_result<
- arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type
- weight_map_type;
- typedef typename boost::property_traits<weight_map_type>::value_type W;
- typedef
- typename detail::map_maker<VertexListGraph, arg_pack_type, tag::distance_map, W>::map_type
- distance_map_type;
- typedef typename boost::property_traits<distance_map_type>::value_type D;
+ typedef typename boost::detail::override_const_property_result<
+ arg_pack_type,
+ boost::graph::keywords::tag::weight_map,
+ edge_weight_t,
+ VertexListGraph
+ >::type weight_map_type;
+ typedef typename boost::property_traits<weight_map_type>::value_type D;
const D inf = arg_pack[_distance_inf || detail::get_max<D>()];
-
+ const D zero_actual = D();
+ const D zero_d = arg_pack[_distance_zero | zero_actual];
+ null_visitor null_vis;
+ astar_visitor<null_visitor> default_visitor(null_vis);
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::visitor,
+ dummy_property_map&
+ >::type vis = arg_pack[_visitor | default_visitor];
+ dummy_property_map dummy_prop;
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::predecessor_map,
+ dummy_property_map&
+ >::type pred_map = arg_pack[_predecessor_map | dummy_prop];
+ boost::detail::make_property_map_from_arg_pack_gen<
+ boost::graph::keywords::tag::rank_map,
+ D
+ > rank_map_gen(zero_actual);
+ typename boost::detail::map_maker<
+ VertexListGraph,
+ arg_pack_type,
+ boost::graph::keywords::tag::rank_map,
+ D
+ >::map_type r_map = rank_map_gen(g, arg_pack);
+ boost::detail::make_property_map_from_arg_pack_gen<
+ boost::graph::keywords::tag::distance_map,
+ D
+ > dist_map_gen(zero_actual);
+ typename boost::detail::map_maker<
+ VertexListGraph,
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_map,
+ D
+ >::map_type dist_map = dist_map_gen(g, arg_pack);
+ weight_map_type w_map = detail::override_const_property(arg_pack, _weight_map, g, edge_weight);
+ typename boost::detail::override_const_property_result<
+ arg_pack_type,
+ boost::graph::keywords::tag::vertex_index_map,
+ vertex_index_t,
+ VertexListGraph
+ >::type v_i_map = detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index);
+ typename boost::detail::map_maker<
+ VertexListGraph,
+ arg_pack_type,
+ boost::graph::keywords::tag::color_map,
+ boost::default_color_type
+ >::map_type c_map = boost::detail::make_color_map_from_arg_pack(g, arg_pack);
+ std::less<D> default_compare;
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_compare,
+ std::less<D>&
+ >::type dist_comp = arg_pack[_distance_compare | default_compare];
+ closed_plus<D> default_combine(inf);
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_combine,
+ closed_plus<D>&
+ >::type dist_comb = arg_pack[_distance_combine | default_combine];
astar_search
(g, s, h,
- arg_pack[_visitor | make_astar_visitor(null_visitor())],
- arg_pack[_predecessor_map | dummy_property_map()],
- detail::make_property_map_from_arg_pack_gen<tag::rank_map, D>(D())(g, arg_pack),
- detail::make_property_map_from_arg_pack_gen<tag::distance_map, W>(W())(g, arg_pack),
- detail::override_const_property(arg_pack, _weight_map, g, edge_weight),
- detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index),
- detail::make_color_map_from_arg_pack(g, arg_pack),
- arg_pack[_distance_compare | std::less<D>()],
- arg_pack[_distance_combine | closed_plus<D>(inf)],
+ vis,
+ pred_map,
+ r_map,
+ dist_map,
+ w_map,
+ v_i_map,
+ c_map,
+ dist_comp,
+ dist_comb,
inf,
- arg_pack[_distance_zero | D()]);
+ zero_d);
}
- // Named parameter interfaces
template <typename VertexListGraph,
typename AStarHeuristic,
typename P, typename T, typename R>
@@ -472,28 +528,73 @@ namespace boost {
// Distance type is the value type of the distance map if there is one,
// otherwise the value type of the weight map.
- typedef
- typename detail::override_const_property_result<
- arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type
- weight_map_type;
- typedef typename boost::property_traits<weight_map_type>::value_type W;
- typedef
- typename detail::map_maker<VertexListGraph, arg_pack_type, tag::distance_map, W>::map_type
- distance_map_type;
- typedef typename boost::property_traits<distance_map_type>::value_type D;
+ typedef typename boost::detail::override_const_property_result<
+ arg_pack_type,
+ boost::graph::keywords::tag::weight_map,
+ edge_weight_t,
+ VertexListGraph
+ >::type weight_map_type;
+ typedef typename boost::property_traits<weight_map_type>::value_type D;
const D inf = arg_pack[_distance_inf || detail::get_max<D>()];
-
+ const D zero_actual = D();
+ const D zero_d = arg_pack[_distance_zero | zero_actual];
+ null_visitor null_vis;
+ astar_visitor<null_visitor> default_visitor(null_vis);
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::visitor,
+ dummy_property_map&
+ >::type vis = arg_pack[_visitor | default_visitor];
+ dummy_property_map dummy_prop;
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::predecessor_map,
+ dummy_property_map&
+ >::type pred_map = arg_pack[_predecessor_map | dummy_prop];
+ boost::detail::make_property_map_from_arg_pack_gen<
+ boost::graph::keywords::tag::rank_map,
+ D
+ > rank_map_gen(zero_actual);
+ typename boost::detail::map_maker<
+ VertexListGraph,
+ arg_pack_type,
+ boost::graph::keywords::tag::rank_map,
+ D
+ >::map_type r_map = rank_map_gen(g, arg_pack);
+ boost::detail::make_property_map_from_arg_pack_gen<
+ boost::graph::keywords::tag::distance_map,
+ D
+ > dist_map_gen(zero_actual);
+ typename boost::detail::map_maker<
+ VertexListGraph,
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_map,
+ D
+ >::map_type dist_map = dist_map_gen(g, arg_pack);
+ weight_map_type w_map = detail::override_const_property(arg_pack, _weight_map, g, edge_weight);
+ std::less<D> default_compare;
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_compare,
+ std::less<D>&
+ >::type dist_comp = arg_pack[_distance_compare | default_compare];
+ closed_plus<D> default_combine(inf);
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_combine,
+ closed_plus<D>&
+ >::type dist_comb = arg_pack[_distance_combine | default_combine];
astar_search_tree
(g, s, h,
- arg_pack[_visitor | make_astar_visitor(null_visitor())],
- arg_pack[_predecessor_map | dummy_property_map()],
- detail::make_property_map_from_arg_pack_gen<tag::rank_map, D>(D())(g, arg_pack),
- detail::make_property_map_from_arg_pack_gen<tag::distance_map, W>(W())(g, arg_pack),
- detail::override_const_property(arg_pack, _weight_map, g, edge_weight),
- arg_pack[_distance_compare | std::less<D>()],
- arg_pack[_distance_combine | closed_plus<D>(inf)],
+ vis,
+ pred_map,
+ r_map,
+ dist_map,
+ w_map,
+ dist_comp,
+ dist_comb,
inf,
- arg_pack[_distance_zero | D()]);
+ zero_d);
}
template <typename VertexListGraph,
@@ -508,25 +609,87 @@ namespace boost {
using namespace boost::graph::keywords;
typedef bgl_named_params<P, T, R> params_type;
BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params)
- typedef
- typename detail::override_const_property_result<
- arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type
- weight_map_type;
+ typedef typename boost::detail::override_const_property_result<
+ arg_pack_type,
+ boost::graph::keywords::tag::weight_map,
+ edge_weight_t,
+ VertexListGraph
+ >::type weight_map_type;
typedef typename boost::property_traits<weight_map_type>::value_type D;
const D inf = arg_pack[_distance_inf || detail::get_max<D>()];
+ const D zero_actual = D();
+ const D zero_d = arg_pack[_distance_zero | zero_actual];
+ null_visitor null_vis;
+ astar_visitor<null_visitor> default_visitor(null_vis);
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::visitor,
+ dummy_property_map&
+ >::type vis = arg_pack[_visitor | default_visitor];
+ dummy_property_map dummy_prop;
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::predecessor_map,
+ dummy_property_map&
+ >::type pred_map = arg_pack[_predecessor_map | dummy_prop];
+ boost::detail::make_property_map_from_arg_pack_gen<
+ boost::graph::keywords::tag::rank_map,
+ D
+ > rank_map_gen(zero_actual);
+ typename boost::detail::map_maker<
+ VertexListGraph,
+ arg_pack_type,
+ boost::graph::keywords::tag::rank_map,
+ D
+ >::map_type r_map = rank_map_gen(g, arg_pack);
+ boost::detail::make_property_map_from_arg_pack_gen<
+ boost::graph::keywords::tag::distance_map,
+ D
+ > dist_map_gen(zero_actual);
+ typename boost::detail::map_maker<
+ VertexListGraph,
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_map,
+ D
+ >::map_type dist_map = dist_map_gen(g, arg_pack);
+ weight_map_type w_map = detail::override_const_property(arg_pack, _weight_map, g, edge_weight);
+ typename boost::detail::map_maker<
+ VertexListGraph,
+ arg_pack_type,
+ boost::graph::keywords::tag::color_map,
+ boost::default_color_type
+ >::map_type c_map = boost::detail::make_color_map_from_arg_pack(g, arg_pack);
+ typename boost::detail::override_const_property_result<
+ arg_pack_type,
+ boost::graph::keywords::tag::vertex_index_map,
+ vertex_index_t,
+ VertexListGraph
+ >::type v_i_map = detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index);
+ std::less<D> default_compare;
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_compare,
+ std::less<D>&
+ >::type dist_comp = arg_pack[_distance_compare | default_compare];
+ closed_plus<D> default_combine(inf);
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_combine,
+ closed_plus<D>&
+ >::type dist_comb = arg_pack[_distance_combine | default_combine];
astar_search_no_init
(g, s, h,
- arg_pack[_visitor | make_astar_visitor(null_visitor())],
- arg_pack[_predecessor_map | dummy_property_map()],
- detail::make_property_map_from_arg_pack_gen<tag::rank_map, D>(D())(g, arg_pack),
- detail::make_property_map_from_arg_pack_gen<tag::distance_map, D>(D())(g, arg_pack),
- detail::override_const_property(arg_pack, _weight_map, g, edge_weight),
- detail::make_color_map_from_arg_pack(g, arg_pack),
- detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index),
- arg_pack[_distance_compare | std::less<D>()],
- arg_pack[_distance_combine | closed_plus<D>(inf)],
+ vis,
+ pred_map,
+ r_map,
+ dist_map,
+ w_map,
+ c_map,
+ v_i_map,
+ dist_comp,
+ dist_comb,
inf,
- arg_pack[_distance_zero | D()]);
+ zero_d);
}
template <typename VertexListGraph,
@@ -541,23 +704,73 @@ namespace boost {
using namespace boost::graph::keywords;
typedef bgl_named_params<P, T, R> params_type;
BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params)
- typedef
- typename detail::override_const_property_result<
- arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type
- weight_map_type;
+ typedef typename boost::detail::override_const_property_result<
+ arg_pack_type,
+ boost::graph::keywords::tag::weight_map,
+ edge_weight_t,
+ VertexListGraph
+ >::type weight_map_type;
typedef typename boost::property_traits<weight_map_type>::value_type D;
const D inf = arg_pack[_distance_inf || detail::get_max<D>()];
+ const D zero_actual = D();
+ const D zero_d = arg_pack[_distance_zero | zero_actual];
+ null_visitor null_vis;
+ astar_visitor<null_visitor> default_visitor(null_vis);
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::visitor,
+ dummy_property_map&
+ >::type vis = arg_pack[_visitor | default_visitor];
+ dummy_property_map dummy_prop;
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::predecessor_map,
+ dummy_property_map&
+ >::type pred_map = arg_pack[_predecessor_map | dummy_prop];
+ boost::detail::make_property_map_from_arg_pack_gen<
+ boost::graph::keywords::tag::rank_map,
+ D
+ > rank_map_gen(zero_actual);
+ typename boost::detail::map_maker<
+ VertexListGraph,
+ arg_pack_type,
+ boost::graph::keywords::tag::rank_map,
+ D
+ >::map_type r_map = rank_map_gen(g, arg_pack);
+ boost::detail::make_property_map_from_arg_pack_gen<
+ boost::graph::keywords::tag::distance_map,
+ D
+ > dist_map_gen(zero_actual);
+ typename boost::detail::map_maker<
+ VertexListGraph,
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_map,
+ D
+ >::map_type dist_map = dist_map_gen(g, arg_pack);
+ weight_map_type w_map = detail::override_const_property(arg_pack, _weight_map, g, edge_weight);
+ std::less<D> default_compare;
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_compare,
+ std::less<D>&
+ >::type dist_comp = arg_pack[_distance_compare | default_compare];
+ closed_plus<D> default_combine(inf);
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::distance_combine,
+ closed_plus<D>&
+ >::type dist_comb = arg_pack[_distance_combine | default_combine];
astar_search_no_init_tree
(g, s, h,
- arg_pack[_visitor | make_astar_visitor(null_visitor())],
- arg_pack[_predecessor_map | dummy_property_map()],
- detail::make_property_map_from_arg_pack_gen<tag::rank_map, D>(D())(g, arg_pack),
- detail::make_property_map_from_arg_pack_gen<tag::distance_map, D>(D())(g, arg_pack),
- detail::override_const_property(arg_pack, _weight_map, g, edge_weight),
- arg_pack[_distance_compare | std::less<D>()],
- arg_pack[_distance_combine | closed_plus<D>(inf)],
+ vis,
+ pred_map,
+ r_map,
+ dist_map,
+ w_map,
+ dist_comp,
+ dist_comb,
inf,
- arg_pack[_distance_zero | D()]);
+ zero_d);
}
} // namespace boost
diff --git a/boost/graph/bipartite.hpp b/boost/graph/bipartite.hpp
index 74316fd537..6e2e707396 100644
--- a/boost/graph/bipartite.hpp
+++ b/boost/graph/bipartite.hpp
@@ -32,7 +32,7 @@ namespace boost {
*/
template <typename Vertex>
- struct bipartite_visitor_error: std::exception
+ struct BOOST_SYMBOL_VISIBLE bipartite_visitor_error: std::exception
{
std::pair <Vertex, Vertex> witnesses;
@@ -212,7 +212,7 @@ namespace boost {
detail::colorize_bipartition (partition_map), std::make_pair (detail::check_bipartition (partition_map),
put_property (partition_map, color_traits <partition_color_t>::white (), on_start_vertex ()))))));
}
- catch (detail::bipartite_visitor_error <vertex_descriptor_t> error)
+ catch (const detail::bipartite_visitor_error <vertex_descriptor_t>&)
{
return false;
}
@@ -299,7 +299,7 @@ namespace boost {
std::make_pair (put_property (partition_map, color_traits <partition_color_t>::white (),
on_start_vertex ()), record_predecessors (predecessor_map, on_tree_edge ())))))));
}
- catch (detail::bipartite_visitor_error <vertex_descriptor_t> error)
+ catch (const detail::bipartite_visitor_error <vertex_descriptor_t>& error)
{
typedef std::vector <vertex_descriptor_t> path_t;
diff --git a/boost/graph/boyer_myrvold_planar_test.hpp b/boost/graph/boyer_myrvold_planar_test.hpp
index dc0158687f..111c5ac4a3 100644
--- a/boost/graph/boyer_myrvold_planar_test.hpp
+++ b/boost/graph/boyer_myrvold_planar_test.hpp
@@ -48,33 +48,31 @@ namespace boost
{
//Dispatch for no planar embedding, no kuratowski subgraph isolation
- typedef typename remove_const
- <
- typename remove_reference
- < typename parameter::binding
- < ArgumentPack, tag::graph>::type
- >::type
- >::type graph_t;
-
- typedef typename parameter::binding
- < ArgumentPack,
+ typedef typename remove_const<
+ typename parameter::value_type<ArgumentPack, tag::graph>::type
+ >::type graph_t;
+
+ typedef typename property_map<
+ graph_t,
+ vertex_index_t
+ >::const_type vertex_default_index_map_t;
+
+ typedef typename parameter::value_type<
+ ArgumentPack,
tag::vertex_index_map,
- typename property_map
- < typename remove_reference<graph_t>::type,
- vertex_index_t>::const_type
- >::type vertex_index_map_t;
+ vertex_default_index_map_t
+ >::type vertex_index_map_t;
+ graph_t const& g = args[graph];
+ vertex_default_index_map_t v_d_map = get(vertex_index, g);
+ vertex_index_map_t v_i_map = args[vertex_index_map | v_d_map];
boyer_myrvold_impl
<graph_t,
vertex_index_map_t,
graph::detail::no_old_handles,
graph::detail::no_embedding
>
- planarity_tester(args[graph],
- args[vertex_index_map |
- get(vertex_index, args[graph])
- ]
- );
+ planarity_tester(g, v_i_map);
return planarity_tester.is_planar() ? true : false;
}
@@ -88,40 +86,51 @@ namespace boost
)
{
//Dispatch for no planar embedding, kuratowski subgraph isolation
- typedef typename remove_const
- <
- typename remove_reference
- < typename parameter::binding
- < ArgumentPack, tag::graph>::type
- >::type
- >::type graph_t;
-
- typedef typename parameter::binding
- < ArgumentPack,
+ typedef typename remove_const<
+ typename parameter::value_type<ArgumentPack, tag::graph>::type
+ >::type graph_t;
+
+ typedef typename property_map<
+ graph_t,
+ vertex_index_t
+ >::const_type vertex_default_index_map_t;
+
+ typedef typename parameter::value_type<
+ ArgumentPack,
tag::vertex_index_map,
- typename property_map<graph_t, vertex_index_t>::type
- >::type vertex_index_map_t;
-
+ vertex_default_index_map_t
+ >::type vertex_index_map_t;
+
+ typedef typename property_map<
+ graph_t,
+ edge_index_t
+ >::const_type edge_default_index_map_t;
+
+ typedef typename parameter::value_type<
+ ArgumentPack,
+ tag::edge_index_map,
+ edge_default_index_map_t
+ >::type edge_index_map_t;
+
+ graph_t const& g = args[graph];
+ vertex_default_index_map_t v_d_map = get(vertex_index, g);
+ vertex_index_map_t v_i_map = args[vertex_index_map | v_d_map];
+ edge_default_index_map_t e_d_map = get(edge_index, g);
+ edge_index_map_t e_i_map = args[edge_index_map | e_d_map];
boyer_myrvold_impl
<graph_t,
vertex_index_map_t,
graph::detail::store_old_handles,
graph::detail::no_embedding
>
- planarity_tester(args[graph],
- args[vertex_index_map |
- get(vertex_index, args[graph])
- ]
- );
+ planarity_tester(g, v_i_map);
if (planarity_tester.is_planar())
return true;
else
{
planarity_tester.extract_kuratowski_subgraph
- (args[kuratowski_subgraph],
- args[edge_index_map|get(edge_index, args[graph])]
- );
+ (args[kuratowski_subgraph], e_i_map);
return false;
}
}
@@ -136,20 +145,24 @@ namespace boost
)
{
//Dispatch for planar embedding, no kuratowski subgraph isolation
- typedef typename remove_const
- <
- typename remove_reference
- < typename parameter::binding
- < ArgumentPack, tag::graph>::type
- >::type
- >::type graph_t;
-
- typedef typename parameter::binding
- < ArgumentPack,
- tag::vertex_index_map,
- typename property_map<graph_t, vertex_index_t>::type
- >::type vertex_index_map_t;
+ typedef typename remove_const<
+ typename parameter::value_type<ArgumentPack, tag::graph>::type
+ >::type graph_t;
+ typedef typename property_map<
+ graph_t,
+ vertex_index_t
+ >::const_type vertex_default_index_map_t;
+
+ typedef typename parameter::value_type<
+ ArgumentPack,
+ tag::vertex_index_map,
+ vertex_default_index_map_t
+ >::type vertex_index_map_t;
+
+ graph_t const& g = args[graph];
+ vertex_default_index_map_t v_d_map = get(vertex_index, g);
+ vertex_index_map_t v_i_map = args[vertex_index_map | v_d_map];
boyer_myrvold_impl
<graph_t,
vertex_index_map_t,
@@ -160,11 +173,7 @@ namespace boost
graph::detail::recursive_lazy_list
#endif
>
- planarity_tester(args[graph],
- args[vertex_index_map |
- get(vertex_index, args[graph])
- ]
- );
+ planarity_tester(g, v_i_map);
if (planarity_tester.is_planar())
{
@@ -184,20 +193,37 @@ namespace boost
)
{
//Dispatch for planar embedding, kuratowski subgraph isolation
- typedef typename remove_const
- <
- typename remove_reference
- < typename parameter::binding
- < ArgumentPack, tag::graph>::type
- >::type
- >::type graph_t;
-
- typedef typename parameter::binding
- < ArgumentPack,
- tag::vertex_index_map,
- typename property_map<graph_t, vertex_index_t>::type
- >::type vertex_index_map_t;
-
+ typedef typename remove_const<
+ typename parameter::value_type<ArgumentPack, tag::graph>::type
+ >::type graph_t;
+
+ typedef typename property_map<
+ graph_t,
+ vertex_index_t
+ >::const_type vertex_default_index_map_t;
+
+ typedef typename parameter::value_type<
+ ArgumentPack,
+ tag::vertex_index_map,
+ vertex_default_index_map_t
+ >::type vertex_index_map_t;
+
+ typedef typename property_map<
+ graph_t,
+ edge_index_t
+ >::const_type edge_default_index_map_t;
+
+ typedef typename parameter::value_type<
+ ArgumentPack,
+ tag::edge_index_map,
+ edge_default_index_map_t
+ >::type edge_index_map_t;
+
+ graph_t const& g = args[graph];
+ vertex_default_index_map_t v_d_map = get(vertex_index, g);
+ vertex_index_map_t v_i_map = args[vertex_index_map | v_d_map];
+ edge_default_index_map_t e_d_map = get(edge_index, g);
+ edge_index_map_t e_i_map = args[edge_index_map | e_d_map];
boyer_myrvold_impl
<graph_t,
vertex_index_map_t,
@@ -208,11 +234,7 @@ namespace boost
graph::detail::recursive_lazy_list
#endif
>
- planarity_tester(args[graph],
- args[vertex_index_map |
- get(vertex_index, args[graph])
- ]
- );
+ planarity_tester(g, v_i_map);
if (planarity_tester.is_planar())
{
@@ -222,9 +244,7 @@ namespace boost
else
{
planarity_tester.extract_kuratowski_subgraph
- (args[kuratowski_subgraph],
- args[edge_index_map | get(edge_index, args[graph])]
- );
+ (args[kuratowski_subgraph], e_i_map);
return false;
}
}
diff --git a/boost/graph/breadth_first_search.hpp b/boost/graph/breadth_first_search.hpp
index b0d10ad5f3..6201076746 100644
--- a/boost/graph/breadth_first_search.hpp
+++ b/boost/graph/breadth_first_search.hpp
@@ -24,11 +24,10 @@
#include <boost/graph/overloading.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/two_bit_color_map.hpp>
+#include <boost/graph/detail/mpi_include.hpp>
#include <boost/concept/assert.hpp>
-#ifdef BOOST_GRAPH_USE_MPI
-#include <boost/graph/distributed/concepts.hpp>
-#endif // BOOST_GRAPH_USE_MPI
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/concepts.hpp>)
namespace boost {
@@ -405,9 +404,7 @@ namespace boost {
} // namespace boost
-#ifdef BOOST_GRAPH_USE_MPI
-# include <boost/graph/distributed/breadth_first_search.hpp>
-#endif
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/breadth_first_search.hpp>)
#endif // BOOST_GRAPH_BREADTH_FIRST_SEARCH_HPP
diff --git a/boost/graph/bron_kerbosch_all_cliques.hpp b/boost/graph/bron_kerbosch_all_cliques.hpp
index b663cf95f0..1dcc04975c 100644
--- a/boost/graph/bron_kerbosch_all_cliques.hpp
+++ b/boost/graph/bron_kerbosch_all_cliques.hpp
@@ -84,7 +84,7 @@ namespace boost
// number = {1},
// year = {2006},
// pages = {28-42}
-// ee = {http://dx.doi.org/10.1016/j.tcs.2006.06.015}
+// ee = {https://doi.org/10.1016/j.tcs.2006.06.015}
// }
/**
diff --git a/boost/graph/connected_components.hpp b/boost/graph/connected_components.hpp
index 9279110f19..117e6a82cd 100644
--- a/boost/graph/connected_components.hpp
+++ b/boost/graph/connected_components.hpp
@@ -16,6 +16,7 @@
#include <boost/graph/properties.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/overloading.hpp>
+#include <boost/graph/detail/mpi_include.hpp>
#include <boost/static_assert.hpp>
#include <boost/concept/assert.hpp>
@@ -100,8 +101,6 @@ namespace boost {
} // namespace boost
-#ifdef BOOST_GRAPH_USE_MPI
-# include <boost/graph/distributed/connected_components.hpp>
-#endif
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/connected_components.hpp>)
#endif // BOOST_GRAPH_CONNECTED_COMPONENTS_HPP
diff --git a/boost/graph/copy.hpp b/boost/graph/copy.hpp
index 6246ebceb1..77aebcde1b 100644
--- a/boost/graph/copy.hpp
+++ b/boost/graph/copy.hpp
@@ -395,7 +395,7 @@ namespace boost {
CopyVertex cv, CopyEdge ce)
: g_out(graph), orig2copy(c), copy_vertex(cv), copy_edge(ce) { }
- template <class Vertex, class Graph>
+ template <class Vertex>
typename graph_traits<NewGraph>::vertex_descriptor copy_one_vertex(Vertex u) const {
typename graph_traits<NewGraph>::vertex_descriptor
new_u = add_vertex(g_out);
diff --git a/boost/graph/cycle_canceling.hpp b/boost/graph/cycle_canceling.hpp
index 46a4b864c8..bc7e69099f 100644
--- a/boost/graph/cycle_canceling.hpp
+++ b/boost/graph/cycle_canceling.hpp
@@ -1,6 +1,6 @@
//=======================================================================
// Copyright 2013 University of Warsaw.
-// Authors: Piotr Wygocki
+// Authors: Piotr Wygocki
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -12,7 +12,7 @@
// by Ahuja, Magnanti, Orlin.
#ifndef BOOST_GRAPH_CYCLE_CANCELING_HPP
-#define BOOST_GRAPH_CYCLE_CANCELING_HPP
+#define BOOST_GRAPH_CYCLE_CANCELING_HPP
#include <numeric>
@@ -20,7 +20,6 @@
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/pending/indirect_cmp.hpp>
-#include <boost/pending/relaxed_heap.hpp>
#include <boost/graph/bellman_ford_shortest_paths.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/detail/augment.hpp>
@@ -32,11 +31,11 @@ namespace boost {
namespace detail {
template <typename PredEdgeMap, typename Vertex>
-class RecordEdgeMapAndCycleVertex
+class RecordEdgeMapAndCycleVertex
: public bellman_visitor<edge_predecessor_recorder<PredEdgeMap, on_edge_relaxed> > {
typedef edge_predecessor_recorder<PredEdgeMap, on_edge_relaxed> PredRec;
public:
- RecordEdgeMapAndCycleVertex(PredEdgeMap pred, Vertex & v) :
+ RecordEdgeMapAndCycleVertex(PredEdgeMap pred, Vertex & v) :
bellman_visitor<PredRec>(PredRec(pred)), m_v(v), m_pred(pred) {}
template <typename Graph, typename Edge>
@@ -63,27 +62,27 @@ template <class Graph, class Pred, class Distance, class Reversed, class Residua
void cycle_canceling(const Graph &g, Weight weight, Reversed rev, ResidualCapacity residual_capacity, Pred pred, Distance distance) {
typedef filtered_graph<const Graph, is_residual_edge<ResidualCapacity> > ResGraph;
ResGraph gres = detail::residual_graph(g, residual_capacity);
-
+
typedef graph_traits<ResGraph> ResGTraits;
typedef graph_traits<Graph> GTraits;
typedef typename ResGTraits::edge_descriptor edge_descriptor;
typedef typename ResGTraits::vertex_descriptor vertex_descriptor;
-
+
typename GTraits::vertices_size_type N = num_vertices(g);
-
+
BGL_FORALL_VERTICES_T(v, g, Graph) {
put(pred, v, edge_descriptor());
put(distance, v, 0);
}
vertex_descriptor cycleStart;
- while(!bellman_ford_shortest_paths(gres, N,
+ while(!bellman_ford_shortest_paths(gres, N,
weight_map(weight).
distance_map(distance).
visitor(detail::RecordEdgeMapAndCycleVertex<Pred, vertex_descriptor>(pred, cycleStart)))) {
detail::augment(g, cycleStart, cycleStart, pred, residual_capacity, rev);
-
+
BGL_FORALL_VERTICES_T(v, g, Graph) {
put(pred, v, edge_descriptor());
put(distance, v, 0);
@@ -97,7 +96,7 @@ namespace detail {
template <class Graph, class P, class T, class R, class ResidualCapacity, class Weight, class Reversed, class Pred, class Distance>
void cycle_canceling_dispatch2(
- const Graph &g,
+ const Graph &g,
Weight weight,
Reversed rev,
ResidualCapacity residual_capacity,
@@ -110,7 +109,7 @@ void cycle_canceling_dispatch2(
//setting default distance map
template <class Graph, class P, class T, class R, class Pred, class ResidualCapacity, class Weight, class Reversed>
void cycle_canceling_dispatch2(
- Graph &g,
+ Graph &g,
Weight weight,
Reversed rev,
ResidualCapacity residual_capacity,
@@ -121,27 +120,27 @@ void cycle_canceling_dispatch2(
std::vector<D> d_map(num_vertices(g));
- cycle_canceling(g, weight, rev, residual_capacity, pred,
+ cycle_canceling(g, weight, rev, residual_capacity, pred,
make_iterator_property_map(d_map.begin(), choose_const_pmap(get_param(params, vertex_index), g, vertex_index)));
}
template <class Graph, class P, class T, class R, class ResidualCapacity, class Weight, class Reversed, class Pred>
void cycle_canceling_dispatch1(
- Graph &g,
- Weight weight,
+ Graph &g,
+ Weight weight,
Reversed rev,
ResidualCapacity residual_capacity,
Pred pred,
const bgl_named_params<P, T, R>& params) {
- cycle_canceling_dispatch2(g, weight, rev,residual_capacity, pred,
+ cycle_canceling_dispatch2(g, weight, rev,residual_capacity, pred,
get_param(params, vertex_distance), params);
}
//setting default predecessors map
template <class Graph, class P, class T, class R, class ResidualCapacity, class Weight, class Reversed>
void cycle_canceling_dispatch1(
- Graph &g,
- Weight weight,
+ Graph &g,
+ Weight weight,
Reversed rev,
ResidualCapacity residual_capacity,
param_not_found,
@@ -151,7 +150,7 @@ void cycle_canceling_dispatch1(
cycle_canceling_dispatch2(g, weight, rev, residual_capacity,
make_iterator_property_map(p_map.begin(), choose_const_pmap(get_param(params, vertex_index), g, vertex_index)),
- get_param(params, vertex_distance), params);
+ get_param(params, vertex_distance), params);
}
}//detail
@@ -159,12 +158,12 @@ void cycle_canceling_dispatch1(
template <class Graph, class P, class T, class R>
void cycle_canceling(Graph &g,
const bgl_named_params<P, T, R>& params) {
- cycle_canceling_dispatch1(g,
+ cycle_canceling_dispatch1(g,
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
- choose_pmap(get_param(params, edge_residual_capacity),
+ choose_pmap(get_param(params, edge_residual_capacity),
g, edge_residual_capacity),
- get_param(params, vertex_predecessor),
+ get_param(params, vertex_predecessor),
params);
}
@@ -178,4 +177,3 @@ void cycle_canceling(Graph &g) {
}
#endif /* BOOST_GRAPH_CYCLE_CANCELING_HPP */
-
diff --git a/boost/graph/depth_first_search.hpp b/boost/graph/depth_first_search.hpp
index cf60e1ac84..0a29de1da5 100644
--- a/boost/graph/depth_first_search.hpp
+++ b/boost/graph/depth_first_search.hpp
@@ -19,6 +19,7 @@
#include <boost/graph/properties.hpp>
#include <boost/graph/visitors.hpp>
#include <boost/graph/named_function_params.hpp>
+#include <boost/graph/detail/mpi_include.hpp>
#include <boost/ref.hpp>
#include <boost/implicit_cast.hpp>
#include <boost/optional.hpp>
@@ -102,7 +103,7 @@ namespace boost {
// The corresponding context shift back from the adjacent vertex occurs
// after all of its out-edges have been examined.
//
- // See http://lists.boost.org/MailArchives/boost/msg48752.php for FAQ.
+ // See https://lists.boost.org/Archives/boost/2003/06/49265.php for FAQ.
template <class IncidenceGraph, class DFSVisitor, class ColorMap,
class TerminatorFunc>
@@ -366,8 +367,6 @@ namespace boost {
}
} // namespace boost
-#ifdef BOOST_GRAPH_USE_MPI
-# include <boost/graph/distributed/depth_first_search.hpp>
-#endif
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/depth_first_search.hpp>)
#endif
diff --git a/boost/graph/detail/adjacency_list.hpp b/boost/graph/detail/adjacency_list.hpp
index 6fb497d7ea..01d400ffdc 100644
--- a/boost/graph/detail/adjacency_list.hpp
+++ b/boost/graph/detail/adjacency_list.hpp
@@ -267,7 +267,7 @@ namespace boost {
: Base(static_cast< Base const& >(x)), m_property(const_cast<self&>(x).m_property) { }
self& operator=(const self& x) {
// NOTE: avoid 'Base::operator=(x);' broken on SGI MIPSpro (bug 55771 of Mozilla).
- static_cast<Base&>(*this) = static_cast< Base const& >(x);
+ static_cast<Base&>(*this) = static_cast< Base const& >(x);
m_property = const_cast<self&>(x).m_property;
return *this;
}
@@ -277,7 +277,7 @@ namespace boost {
: Base(static_cast< Base&& >(x)), m_property(std::move(x.m_property)) { }
self& operator=(self&& x) {
// NOTE: avoid 'Base::operator=(x);' broken on SGI MIPSpro (bug 55771 of Mozilla).
- static_cast<Base&>(*this) = static_cast< Base&& >(x);
+ static_cast<Base&>(*this) = static_cast< Base&& >(x);
m_property = std::move(x.m_property);
return *this;
}
@@ -2051,16 +2051,15 @@ namespace boost {
if ((*ei).get_target() > u)
--(*ei).get_target();
}
+
template <class EdgeList, class vertex_descriptor>
inline void
reindex_edge_list(EdgeList& el, vertex_descriptor u,
boost::disallow_parallel_edge_tag)
{
- typename EdgeList::iterator ei = el.begin(), e_end = el.end();
- while (ei != e_end) {
- typename EdgeList::value_type ce = *ei;
- ++ei;
- if (ce.get_target() > u) {
+ for(typename EdgeList::iterator ei = el.begin(); ei != el.end(); ++ei) {
+ if (ei->get_target() > u) {
+ typename EdgeList::value_type ce = *ei;
el.erase(ce);
--ce.get_target();
el.insert(ce);
diff --git a/boost/graph/detail/array_binary_tree.hpp b/boost/graph/detail/array_binary_tree.hpp
index fd403d1f30..a594ba6bf8 100644
--- a/boost/graph/detail/array_binary_tree.hpp
+++ b/boost/graph/detail/array_binary_tree.hpp
@@ -14,7 +14,6 @@
#include <iterator>
#include <functional>
#include <boost/config.hpp>
-#include <boost/iterator.hpp>
namespace boost {
@@ -43,9 +42,12 @@ public:
struct children_type {
struct iterator
- : boost::iterator<std::bidirectional_iterator_tag, ArrayBinaryTreeNode,
- difference_type, array_binary_tree_node*, ArrayBinaryTreeNode&>
{ // replace with iterator_adaptor implementation -JGS
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef ArrayBinaryTreeNode value_type;
+ typedef size_type difference_type;
+ typedef array_binary_tree_node* pointer;
+ typedef ArrayBinaryTreeNode& reference;
inline iterator() : i(0), n(0) { }
inline iterator(const iterator& x) : r(x.r), i(x.i), n(x.n), id(x.id) { }
diff --git a/boost/graph/detail/empty_header.hpp b/boost/graph/detail/empty_header.hpp
new file mode 100644
index 0000000000..fde3672551
--- /dev/null
+++ b/boost/graph/detail/empty_header.hpp
@@ -0,0 +1,10 @@
+#ifndef BOOST_GRAPH_DETAIL_EMPTY_HEADER_HPP_INCLUDED
+#define BOOST_GRAPH_DETAIL_EMPTY_HEADER_HPP_INCLUDED
+
+// Copyright 2018 Peter Dimov
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0 (See accompanying file
+// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+#endif // #ifndef BOOST_GRAPH_DETAIL_EMPTY_HEADER_HPP_INCLUDED
diff --git a/boost/graph/detail/geodesic.hpp b/boost/graph/detail/geodesic.hpp
index 57352b1adc..b94482ccdb 100644
--- a/boost/graph/detail/geodesic.hpp
+++ b/boost/graph/detail/geodesic.hpp
@@ -33,7 +33,7 @@ namespace boost
// pages = {466--484},
// priority = {0},
// title = {A Graph-theoretic perspective on centrality},
-// url = {http://dx.doi.org/10.1016/j.socnet.2005.11.005},
+// url = {https://doi.org/10.1016/j.socnet.2005.11.005},
// volume = {28},
// year = {2006}
// }
diff --git a/boost/graph/detail/mpi_include.hpp b/boost/graph/detail/mpi_include.hpp
new file mode 100644
index 0000000000..9e1c8858aa
--- /dev/null
+++ b/boost/graph/detail/mpi_include.hpp
@@ -0,0 +1,16 @@
+#ifndef BOOST_GRAPH_DETAIL_MPI_INCLUDE_HPP_INCLUDED
+#define BOOST_GRAPH_DETAIL_MPI_INCLUDE_HPP_INCLUDED
+
+// Copyright 2018 Peter Dimov
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0 (See accompanying file
+// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+#if defined BOOST_GRAPH_USE_MPI
+# define BOOST_GRAPH_MPI_INCLUDE(x) x
+#else
+# define BOOST_GRAPH_MPI_INCLUDE(x) <boost/graph/detail/empty_header.hpp>
+#endif
+
+#endif // #ifndef BOOST_GRAPH_DETAIL_MPI_INCLUDE_HPP_INCLUDED
diff --git a/boost/graph/detail/read_graphviz_new.hpp b/boost/graph/detail/read_graphviz_new.hpp
index 81221c0b25..8d3eea5229 100644
--- a/boost/graph/detail/read_graphviz_new.hpp
+++ b/boost/graph/detail/read_graphviz_new.hpp
@@ -5,13 +5,13 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
-// read_graphviz_new.hpp -
+// read_graphviz_new.hpp -
// Initialize a model of the BGL's MutableGraph concept and an associated
// collection of property maps using a graph expressed in the GraphViz
-// DOT Language.
+// DOT Language.
//
// Based on the grammar found at:
-// http://www.graphviz.org/cvs/doc/info/lang.html
+// https://web.archive.org/web/20041213234742/http://www.graphviz.org/cvs/doc/info/lang.html
//
// Jeremiah rewrite used grammar found at:
// http://www.graphviz.org/doc/info/lang.html
diff --git a/boost/graph/detail/read_graphviz_spirit.hpp b/boost/graph/detail/read_graphviz_spirit.hpp
index 2ba09cc0a4..d10bbc720c 100644
--- a/boost/graph/detail/read_graphviz_spirit.hpp
+++ b/boost/graph/detail/read_graphviz_spirit.hpp
@@ -5,13 +5,13 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
-// read_graphviz_spirit.hpp -
+// read_graphviz_spirit.hpp -
// Initialize a model of the BGL's MutableGraph concept and an associated
// collection of property maps using a graph expressed in the GraphViz
-// DOT Language.
+// DOT Language.
//
// Based on the grammar found at:
-// http://www.graphviz.org/cvs/doc/info/lang.html
+// https://web.archive.org/web/20041213234742/http://www.graphviz.org/cvs/doc/info/lang.html
//
// See documentation for this code at:
// http://www.boost.org/libs/graph/doc/read_graphviz.html
diff --git a/boost/graph/dijkstra_shortest_paths.hpp b/boost/graph/dijkstra_shortest_paths.hpp
index 10e40f828a..f4a2a2474f 100644
--- a/boost/graph/dijkstra_shortest_paths.hpp
+++ b/boost/graph/dijkstra_shortest_paths.hpp
@@ -22,11 +22,11 @@
#include <boost/graph/relax.hpp>
#include <boost/pending/indirect_cmp.hpp>
#include <boost/graph/exception.hpp>
-#include <boost/pending/relaxed_heap.hpp>
#include <boost/graph/overloading.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/graph/detail/d_ary_heap.hpp>
#include <boost/graph/two_bit_color_map.hpp>
+#include <boost/graph/detail/mpi_include.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/property_map/vector_property_map.hpp>
#include <boost/type_traits.hpp>
@@ -53,18 +53,13 @@ namespace boost {
* @param old_distance the previous distance to @p vertex
*/
template<typename Buffer, typename Vertex, typename DistanceType>
- inline void
+ inline void
dijkstra_queue_update(Buffer& Q, Vertex vertex, DistanceType old_distance)
{
(void)old_distance;
Q.update(vertex);
}
-#ifdef BOOST_GRAPH_DIJKSTRA_TESTING
- // This is a misnomer now: it now just refers to the "default heap", which is
- // currently d-ary (d=4) but can be changed by a #define.
- static bool dijkstra_relaxed_heap = true;
-#endif
template <class Visitor, class Graph>
struct DijkstraVisitorConcept {
@@ -129,7 +124,7 @@ namespace boost {
template <class Edge, class Graph>
void tree_edge(Edge e, Graph& g) {
- bool decreased = relax(e, g, m_weight, m_predecessor, m_distance,
+ bool decreased = relax_target(e, g, m_weight, m_predecessor, m_distance,
m_combine, m_compare);
if (decreased)
m_vis.edge_relaxed(e, g);
@@ -140,7 +135,7 @@ namespace boost {
void gray_target(Edge e, Graph& g) {
D old_distance = get(m_distance, target(e, g));
- bool decreased = relax(e, g, m_weight, m_predecessor, m_distance,
+ bool decreased = relax_target(e, g, m_weight, m_predecessor, m_distance,
m_combine, m_compare);
if (decreased) {
dijkstra_queue_update(m_Q, target(e, g), old_distance);
@@ -187,7 +182,7 @@ namespace boost {
// The test here is equivalent to e_weight < 0 if m_combine has a
// cancellation law, but always returns false when m_combine is a
// projection operator.
- if (m_compare(m_combine(m_zero, get(m_weight, e)), m_zero))
+ if (m_compare(m_combine(m_zero, get(m_weight, e)), m_zero))
boost::throw_exception(negative_edge());
// End of test for negative-weight edges.
@@ -345,25 +340,7 @@ namespace boost {
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
-#ifdef BOOST_GRAPH_DIJKSTRA_TESTING
- if (!dijkstra_relaxed_heap) {
- typedef mutable_queue<Vertex, std::vector<Vertex>, IndirectCmp, IndexMap>
- MutableQueue;
-
- MutableQueue Q(num_vertices(g), icmp, index_map);
- detail::dijkstra_bfs_visitor<DijkstraVisitor, MutableQueue, WeightMap,
- PredecessorMap, DistanceMap, Combine, Compare>
- bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero);
-
- breadth_first_visit(g, s_begin, s_end, Q, bfs_vis, color);
- return;
- }
-#endif // BOOST_GRAPH_DIJKSTRA_TESTING
-
-#ifdef BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP
- typedef relaxed_heap<Vertex, IndirectCmp, IndexMap> MutableQueue;
- MutableQueue Q(num_vertices(g), icmp, index_map);
-#else // Now the default: use a d-ary heap
+ // Now the default: use a d-ary heap
boost::scoped_array<std::size_t> index_in_heap_map_holder;
typedef
detail::vertex_property_map_generator<Graph, IndexMap, std::size_t>
@@ -374,7 +351,6 @@ namespace boost {
typedef d_ary_heap_indirect<Vertex, 4, IndexInHeapMap, DistanceMap, Compare>
MutableQueue;
MutableQueue Q(distance, index_in_heap, compare);
-#endif // Relaxed heap
detail::dijkstra_bfs_visitor<DijkstraVisitor, MutableQueue, WeightMap,
PredecessorMap, DistanceMap, Combine, Compare>
@@ -406,7 +382,7 @@ namespace boost {
template <class VertexListGraph, class SourceInputIter, class DijkstraVisitor,
class PredecessorMap, class DistanceMap,
class WeightMap, class IndexMap, class Compare, class Combine,
- class DistInf, class DistZero, typename T, typename Tag,
+ class DistInf, class DistZero, typename T, typename Tag,
typename Base>
inline void
dijkstra_shortest_paths
@@ -429,7 +405,7 @@ namespace boost {
template <class VertexListGraph, class DijkstraVisitor,
class PredecessorMap, class DistanceMap,
class WeightMap, class IndexMap, class Compare, class Combine,
- class DistInf, class DistZero, typename T, typename Tag,
+ class DistInf, class DistZero, typename T, typename Tag,
typename Base>
inline void
dijkstra_shortest_paths
@@ -564,7 +540,7 @@ namespace boost {
choose_param(get_param(params, distance_compare_t()),
std::less<D>()),
choose_param(get_param(params, distance_combine_t()),
- closed_plus<D>(inf)),
+ std::plus<D>()),
inf,
choose_param(get_param(params, distance_zero_t()),
D()),
@@ -616,8 +592,6 @@ namespace boost {
} // namespace boost
-#ifdef BOOST_GRAPH_USE_MPI
-# include <boost/graph/distributed/dijkstra_shortest_paths.hpp>
-#endif
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/dijkstra_shortest_paths.hpp>)
#endif // BOOST_GRAPH_DIJKSTRA_HPP
diff --git a/boost/graph/dijkstra_shortest_paths_no_color_map.hpp b/boost/graph/dijkstra_shortest_paths_no_color_map.hpp
index b1a9ef5890..ae8769fc6f 100644
--- a/boost/graph/dijkstra_shortest_paths_no_color_map.hpp
+++ b/boost/graph/dijkstra_shortest_paths_no_color_map.hpp
@@ -13,7 +13,6 @@
#include <boost/pending/indirect_cmp.hpp>
#include <boost/graph/relax.hpp>
-#include <boost/pending/relaxed_heap.hpp>
#include <boost/graph/detail/d_ary_heap.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/iteration_macros.hpp>
@@ -41,19 +40,12 @@ namespace boost {
{
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
typedef typename property_traits<DistanceMap>::value_type Distance;
-
+
typedef indirect_cmp<DistanceMap, DistanceCompare> DistanceIndirectCompare;
DistanceIndirectCompare
distance_indirect_compare(distance_map, distance_compare);
-
- // Choose vertex queue type
-#if BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP
- typedef relaxed_heap<Vertex, DistanceIndirectCompare, VertexIndexMap>
- VertexQueue;
- VertexQueue vertex_queue(num_vertices(graph),
- distance_indirect_compare,
- index_map);
-#else
+
+
// Default - use d-ary heap (d = 4)
typedef
detail::vertex_property_map_generator<Graph, VertexIndexMap, std::size_t>
@@ -62,54 +54,53 @@ namespace boost {
typedef
d_ary_heap_indirect<Vertex, 4, IndexInHeapMap, DistanceMap, DistanceCompare>
VertexQueue;
-
+
boost::scoped_array<std::size_t> index_in_heap_map_holder;
IndexInHeapMap index_in_heap =
IndexInHeapMapHelper::build(graph, index_map,
- index_in_heap_map_holder);
+ index_in_heap_map_holder);
VertexQueue vertex_queue(distance_map, index_in_heap, distance_compare);
-#endif
-
+
// Add vertex to the queue
vertex_queue.push(start_vertex);
-
+
// Starting vertex will always be the first discovered vertex
visitor.discover_vertex(start_vertex, graph);
-
+
while (!vertex_queue.empty()) {
Vertex min_vertex = vertex_queue.top();
vertex_queue.pop();
-
+
visitor.examine_vertex(min_vertex, graph);
-
+
// Check if any other vertices can be reached
Distance min_vertex_distance = get(distance_map, min_vertex);
-
+
if (!distance_compare(min_vertex_distance, distance_infinity)) {
// This is the minimum vertex, so all other vertices are unreachable
return;
}
-
+
// Examine neighbors of min_vertex
BGL_FORALL_OUTEDGES_T(min_vertex, current_edge, graph, Graph) {
visitor.examine_edge(current_edge, graph);
-
+
// Check if the edge has a negative weight
if (distance_compare(get(weight_map, current_edge), distance_zero)) {
boost::throw_exception(negative_edge());
}
-
+
// Extract the neighboring vertex and get its distance
Vertex neighbor_vertex = target(current_edge, graph);
Distance neighbor_vertex_distance = get(distance_map, neighbor_vertex);
- bool is_neighbor_undiscovered =
+ bool is_neighbor_undiscovered =
!distance_compare(neighbor_vertex_distance, distance_infinity);
// Attempt to relax the edge
- bool was_edge_relaxed = relax(current_edge, graph, weight_map,
+ bool was_edge_relaxed = relax_target(current_edge, graph, weight_map,
predecessor_map, distance_map,
distance_weight_combine, distance_compare);
-
+
if (was_edge_relaxed) {
visitor.edge_relaxed(current_edge, graph);
if (is_neighbor_undiscovered) {
@@ -121,9 +112,9 @@ namespace boost {
} else {
visitor.edge_not_relaxed(current_edge, graph);
}
-
+
} // end out edge iteration
-
+
visitor.finish_vertex(min_vertex, graph);
} // end while queue not empty
}
@@ -150,17 +141,17 @@ namespace boost {
// Initialize vertices
BGL_FORALL_VERTICES_T(current_vertex, graph, Graph) {
visitor.initialize_vertex(current_vertex, graph);
-
+
// Default all distances to infinity
put(distance_map, current_vertex, distance_infinity);
-
+
// Default all vertex predecessors to the vertex itself
put(predecessor_map, current_vertex, current_vertex);
}
-
+
// Set distance for start_vertex to zero
put(distance_map, start_vertex, distance_zero);
-
+
// Pass everything on to the no_init version
dijkstra_shortest_paths_no_color_map_no_init(graph,
start_vertex, predecessor_map, distance_map, weight_map,
@@ -195,7 +186,7 @@ namespace boost {
choose_param(get_param(params, distance_compare_t()),
std::less<DistanceType>()),
choose_param(get_param(params, distance_combine_t()),
- closed_plus<DistanceType>(inf)),
+ std::plus<DistanceType>()),
inf,
choose_param(get_param(params, distance_zero_t()),
DistanceType()),
@@ -216,7 +207,7 @@ namespace boost {
typedef typename property_traits<WeightMap>::value_type DistanceType;
typename std::vector<DistanceType>::size_type
vertex_count = is_default_param(distance_map) ? num_vertices(graph) : 1;
-
+
std::vector<DistanceType> default_distance_map(vertex_count);
detail::dijkstra_no_color_map_dispatch2
diff --git a/boost/graph/dimacs.hpp b/boost/graph/dimacs.hpp
index 3e8407dfab..12adba81e6 100644
--- a/boost/graph/dimacs.hpp
+++ b/boost/graph/dimacs.hpp
@@ -21,7 +21,7 @@
namespace boost { namespace graph {
-class dimacs_exception : public std::exception {};
+class BOOST_SYMBOL_VISIBLE dimacs_exception : public std::exception {};
class dimacs_basic_reader {
public:
diff --git a/boost/graph/distributed/detail/mpi_process_group.ipp b/boost/graph/distributed/detail/mpi_process_group.ipp
index c157387be9..94050da9c2 100644
--- a/boost/graph/distributed/detail/mpi_process_group.ipp
+++ b/boost/graph/distributed/detail/mpi_process_group.ipp
@@ -839,10 +839,19 @@ all_gather(const mpi_process_group& pg, InputIterator first,
&sizes[0], 1, MPI_INT,
communicator(pg));
BOOST_ASSERT(result == MPI_SUCCESS);
+ (void)result;
// Adjust sizes based on the number of bytes
- std::transform(sizes.begin(), sizes.end(), sizes.begin(),
- std::bind2nd(std::multiplies<int>(), sizeof(T)));
+ //
+ // std::transform(sizes.begin(), sizes.end(), sizes.begin(),
+ // std::bind2nd(std::multiplies<int>(), sizeof(T)));
+ //
+ // std::bind2nd has been removed from C++17
+
+ for( std::size_t i = 0, n = sizes.size(); i < n; ++i )
+ {
+ sizes[ i ] *= sizeof( T );
+ }
// Compute displacements
std::vector<int> displacements;
@@ -880,6 +889,7 @@ process_subgroup(const mpi_process_group& pg,
MPI_Group current_group;
int result = MPI_Comm_group(communicator(pg), &current_group);
BOOST_ASSERT(result == MPI_SUCCESS);
+ (void)result;
MPI_Group new_group;
result = MPI_Group_incl(current_group, ranks.size(), &ranks[0], &new_group);
diff --git a/boost/graph/exception.hpp b/boost/graph/exception.hpp
index 382d671928..f1f13dcf89 100644
--- a/boost/graph/exception.hpp
+++ b/boost/graph/exception.hpp
@@ -15,36 +15,36 @@
namespace boost {
- struct bad_graph : public std::invalid_argument {
+ struct BOOST_SYMBOL_VISIBLE bad_graph : public std::invalid_argument {
bad_graph(const std::string& what_arg)
: std::invalid_argument(what_arg) { }
};
- struct not_a_dag : public bad_graph {
+ struct BOOST_SYMBOL_VISIBLE not_a_dag : public bad_graph {
not_a_dag()
: bad_graph("The graph must be a DAG.")
{ }
};
- struct negative_edge : public bad_graph {
+ struct BOOST_SYMBOL_VISIBLE negative_edge : public bad_graph {
negative_edge()
: bad_graph("The graph may not contain an edge with negative weight.")
{ }
};
- struct negative_cycle : public bad_graph {
+ struct BOOST_SYMBOL_VISIBLE negative_cycle : public bad_graph {
negative_cycle()
: bad_graph("The graph may not contain negative cycles.")
{ }
};
- struct not_connected : public bad_graph {
+ struct BOOST_SYMBOL_VISIBLE not_connected : public bad_graph {
not_connected()
: bad_graph("The graph must be connected.")
{ }
};
- struct not_complete : public bad_graph {
+ struct BOOST_SYMBOL_VISIBLE not_complete : public bad_graph {
not_complete()
: bad_graph("The graph must be complete.")
{ }
diff --git a/boost/graph/exterior_property.hpp b/boost/graph/exterior_property.hpp
index af6df8180b..f920939f3a 100644
--- a/boost/graph/exterior_property.hpp
+++ b/boost/graph/exterior_property.hpp
@@ -14,8 +14,7 @@
namespace boost {
namespace detail {
// The vector matrix provides a little abstraction over vector
- // types that makes matrices easier to work with. Note that it's
- // non-copyable, meaning you should be passing it by value.
+ // types that makes matrices easier to work with.
template <typename Value>
struct vector_matrix
{
@@ -28,7 +27,7 @@ namespace detail {
typedef container_type* pointer;
typedef typename matrix_type::size_type size_type;
- // Instantiate the matrix over n elements (creates an nxn matrix).
+ // Instantiate the matrix over n elements (creates an n by n matrix).
// The graph has to be passed in order to ensure the index maps
// are constructed correctly when returning indexible elements.
inline vector_matrix(size_type n)
diff --git a/boost/graph/fruchterman_reingold.hpp b/boost/graph/fruchterman_reingold.hpp
index 01d080a418..24e1ae8cfa 100644
--- a/boost/graph/fruchterman_reingold.hpp
+++ b/boost/graph/fruchterman_reingold.hpp
@@ -14,6 +14,7 @@
#include <boost/graph/named_function_params.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/topology.hpp> // For topology concepts
+#include <boost/graph/detail/mpi_include.hpp>
#include <vector>
#include <list>
#include <algorithm> // for std::min and std::max
@@ -433,8 +434,6 @@ fruchterman_reingold_force_directed_layout
} // end namespace boost
-#ifdef BOOST_GRAPH_USE_MPI
-# include <boost/graph/distributed/fruchterman_reingold.hpp>
-#endif
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/fruchterman_reingold.hpp>)
#endif // BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP
diff --git a/boost/graph/graph_test.hpp b/boost/graph/graph_test.hpp
deleted file mode 100644
index 69d89f34f2..0000000000
--- a/boost/graph/graph_test.hpp
+++ /dev/null
@@ -1,384 +0,0 @@
-//=======================================================================
-// Copyright 2002 Indiana University.
-// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
-//
-// Distributed under the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//=======================================================================
-
-#ifndef BOOST_GRAPH_TEST_HPP
-#define BOOST_GRAPH_TEST_HPP
-
-#include <vector>
-#include <boost/test/minimal.hpp>
-#include <boost/graph/filtered_graph.hpp>
-#include <boost/graph/iteration_macros.hpp>
-#include <boost/graph/isomorphism.hpp>
-#include <boost/graph/copy.hpp>
-#include <boost/graph/graph_utility.hpp> // for connects
-#include <boost/range.hpp>
-#include <boost/range/algorithm/find_if.hpp>
-
-
-// UNDER CONSTRUCTION
-
-namespace boost {
-
- template <typename Graph>
- struct graph_test
- {
-
- typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
- typedef typename graph_traits<Graph>::edge_descriptor edge_t;
- typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
- typedef typename graph_traits<Graph>::degree_size_type deg_size_t;
- typedef typename graph_traits<Graph>::edges_size_type e_size_t;
- typedef typename graph_traits<Graph>::out_edge_iterator out_edge_iter;
- typedef typename property_map<Graph, vertex_index_t>::type index_map_t;
- typedef iterator_property_map<typename std::vector<vertex_t>::iterator,
- index_map_t,vertex_t,vertex_t&> IsoMap;
-
- struct ignore_vertex {
- ignore_vertex() { }
- ignore_vertex(vertex_t v) : v(v) { }
- bool operator()(vertex_t x) const { return x != v; }
- vertex_t v;
- };
- struct ignore_edge {
- ignore_edge() { }
- ignore_edge(edge_t e) : e(e) { }
- bool operator()(edge_t x) const { return x != e; }
- edge_t e;
- };
- struct ignore_edges {
- ignore_edges(vertex_t s, vertex_t t, const Graph& g)
- : s(s), t(t), g(g) { }
- bool operator()(edge_t x) const {
- return !(source(x, g) == s && target(x, g) == t);
- }
- vertex_t s; vertex_t t; const Graph& g;
- };
-
- //=========================================================================
- // Traversal Operations
-
- void test_incidence_graph
- (const std::vector<vertex_t>& vertex_set,
- const std::vector< std::pair<vertex_t, vertex_t> >& edge_set,
- const Graph& g)
- {
- typedef typename std::vector<vertex_t>::const_iterator vertex_iter;
- typedef typename std::vector< std::pair<vertex_t, vertex_t> >
- ::const_iterator edge_iter;
- typedef typename graph_traits<Graph>::out_edge_iterator out_edge_iter;
-
- for (vertex_iter ui = vertex_set.begin(); ui != vertex_set.end(); ++ui) {
- vertex_t u = *ui;
- std::vector<vertex_t> adj;
- for (edge_iter e = edge_set.begin(); e != edge_set.end(); ++e)
- if (e->first == u)
- adj.push_back(e->second);
-
- std::pair<out_edge_iter, out_edge_iter> p = out_edges(u, g);
- BOOST_CHECK(out_degree(u, g) == adj.size());
- BOOST_CHECK(deg_size_t(std::distance(p.first, p.second))
- == out_degree(u, g));
- for (; p.first != p.second; ++p.first) {
- edge_t e = *p.first;
- BOOST_CHECK(source(e, g) == u);
- BOOST_CHECK(container_contains(adj, target(e, g)) == true);
- }
- }
- }
-
- void test_bidirectional_graph
- (const std::vector<vertex_t>& vertex_set,
- const std::vector< std::pair<vertex_t, vertex_t> >& edge_set,
- const Graph& g)
- {
- typedef typename std::vector<vertex_t>::const_iterator vertex_iter;
- typedef typename std::vector< std::pair<vertex_t, vertex_t> >
- ::const_iterator edge_iter;
- typedef typename graph_traits<Graph>::in_edge_iterator in_edge_iter;
-
- for (vertex_iter vi = vertex_set.begin(); vi != vertex_set.end(); ++vi) {
- vertex_t v = *vi;
- std::vector<vertex_t> inv_adj;
- for (edge_iter e = edge_set.begin(); e != edge_set.end(); ++e)
- if (e->second == v)
- inv_adj.push_back(e->first);
-
- std::pair<in_edge_iter, in_edge_iter> p = in_edges(v, g);
- BOOST_CHECK(in_degree(v, g) == inv_adj.size());
- BOOST_CHECK(deg_size_t(std::distance(p.first, p.second))
- == in_degree(v, g));
- for (; p.first != p.second; ++p.first) {
- edge_t e = *p.first;
- BOOST_CHECK(target(e, g) == v);
- BOOST_CHECK(container_contains(inv_adj, source(e, g)) == true);
- }
- }
- }
-
- void test_adjacency_graph
- (const std::vector<vertex_t>& vertex_set,
- const std::vector< std::pair<vertex_t,vertex_t> >& edge_set,
- const Graph& g)
- {
- typedef typename std::vector<vertex_t>::const_iterator vertex_iter;
- typedef typename std::vector<std::pair<vertex_t,vertex_t> >
- ::const_iterator edge_iter;
- typedef typename graph_traits<Graph>::adjacency_iterator adj_iter;
-
- for (vertex_iter ui = vertex_set.begin(); ui != vertex_set.end(); ++ui) {
- vertex_t u = *ui;
- std::vector<vertex_t> adj;
- for (edge_iter e = edge_set.begin(); e != edge_set.end(); ++e)
- if (e->first == u)
- adj.push_back(e->second);
-
- std::pair<adj_iter, adj_iter> p = adjacent_vertices(u, g);
- BOOST_CHECK(deg_size_t(std::distance(p.first, p.second)) == adj.size());
- for (; p.first != p.second; ++p.first) {
- vertex_t v = *p.first;
- BOOST_CHECK(container_contains(adj, v) == true);
- }
- }
- }
-
- void test_vertex_list_graph
- (const std::vector<vertex_t>& vertex_set, const Graph& g)
- {
- typedef typename graph_traits<Graph>::vertex_iterator v_iter;
- std::pair<v_iter, v_iter> p = vertices(g);
- BOOST_CHECK(num_vertices(g) == vertex_set.size());
- v_size_t n = (size_t)std::distance(p.first, p.second);
- BOOST_CHECK(n == num_vertices(g));
- for (; p.first != p.second; ++p.first) {
- vertex_t v = *p.first;
- BOOST_CHECK(container_contains(vertex_set, v) == true);
- }
- }
-
- void test_edge_list_graph
- (const std::vector<vertex_t>& vertex_set,
- const std::vector< std::pair<vertex_t, vertex_t> >& edge_set,
- const Graph& g)
- {
- typedef typename graph_traits<Graph>::edge_iterator e_iter;
- std::pair<e_iter, e_iter> p = edges(g);
- BOOST_CHECK(num_edges(g) == edge_set.size());
- e_size_t m = std::distance(p.first, p.second);
- BOOST_CHECK(m == num_edges(g));
- for (; p.first != p.second; ++p.first) {
- edge_t e = *p.first;
- BOOST_CHECK(find_if(edge_set, connects(source(e, g), target(e, g), g)) != boost::end(edge_set));
- BOOST_CHECK(container_contains(vertex_set, source(e, g)) == true);
- BOOST_CHECK(container_contains(vertex_set, target(e, g)) == true);
- }
- }
-
- void test_adjacency_matrix
- (const std::vector<vertex_t>& vertex_set,
- const std::vector< std::pair<vertex_t, vertex_t> >& edge_set,
- const Graph& g)
- {
- std::pair<edge_t, bool> p;
- for (typename std::vector<std::pair<vertex_t, vertex_t> >
- ::const_iterator i = edge_set.begin();
- i != edge_set.end(); ++i) {
- p = edge(i->first, i->second, g);
- BOOST_CHECK(p.second == true);
- BOOST_CHECK(source(p.first, g) == i->first);
- BOOST_CHECK(target(p.first, g) == i->second);
- }
- typename std::vector<vertex_t>::const_iterator j, k;
- for (j = vertex_set.begin(); j != vertex_set.end(); ++j)
- for (k = vertex_set.begin(); k != vertex_set.end(); ++k) {
- p = edge(*j, *k, g);
- if (p.second == true)
- BOOST_CHECK(find_if(edge_set,
- connects(source(p.first, g), target(p.first, g), g)) != boost::end(edge_set));
- }
- }
-
- //=========================================================================
- // Mutating Operations
-
- void test_add_vertex(Graph& g)
- {
- Graph cpy;
- std::vector<vertex_t> iso_vec(num_vertices(g));
- IsoMap iso_map(iso_vec.begin(), get(vertex_index, g));
- copy_graph(g, cpy, orig_to_copy(iso_map));
-
- BOOST_CHECK((verify_isomorphism(g, cpy, iso_map)));
-
- vertex_t v = add_vertex(g);
-
- BOOST_CHECK(num_vertices(g) == num_vertices(cpy) + 1);
-
- BOOST_CHECK(out_degree(v, g) == 0);
-
- // Make sure the rest of the graph stayed the same
- BOOST_CHECK((verify_isomorphism
- (make_filtered_graph(g, keep_all(), ignore_vertex(v)), cpy,
- iso_map)));
- }
-
- void test_add_edge(vertex_t u, vertex_t v, Graph& g)
- {
- Graph cpy;
- std::vector<vertex_t> iso_vec(num_vertices(g));
- IsoMap iso_map(iso_vec.begin(), get(vertex_index, g));
- copy_graph(g, cpy, orig_to_copy(iso_map));
-
- bool parallel_edge_exists = container_contains(adjacent_vertices(u, g), v);
-
- std::pair<edge_t, bool> p = add_edge(u, v, g);
- edge_t e = p.first;
- bool added = p.second;
-
- if (is_undirected(g) && u == v) // self edge
- BOOST_CHECK(added == false);
- else if (parallel_edge_exists)
- BOOST_CHECK(allows_parallel_edges(g) && added == true
- || !allows_parallel_edges(g) && added == false);
- else
- BOOST_CHECK(added == true);
-
- if (p.second == true) { // edge added
- BOOST_CHECK(num_edges(g) == num_edges(cpy) + 1);
-
- BOOST_CHECK(container_contains(out_edges(u, g), e) == true);
-
- BOOST_CHECK((verify_isomorphism
- (make_filtered_graph(g, ignore_edge(e)), cpy, iso_map)));
- }
- else { // edge not added
- if (! (is_undirected(g) && u == v)) {
- // e should be a parallel edge
- BOOST_CHECK(source(e, g) == u);
- BOOST_CHECK(target(e, g) == v);
- }
- // The graph should not be changed.
- BOOST_CHECK((verify_isomorphism(g, cpy, iso_map)));
- }
- } // test_add_edge()
-
-
- void test_remove_edge(vertex_t u, vertex_t v, Graph& g)
- {
- Graph cpy;
- std::vector<vertex_t> iso_vec(num_vertices(g));
- IsoMap iso_map(iso_vec.begin(), get(vertex_index, g));
- copy_graph(g, cpy, orig_to_copy(iso_map));
-
- deg_size_t occurances = count(adjacent_vertices(u, g), v);
-
- remove_edge(u, v, g);
-
- BOOST_CHECK(num_edges(g) + occurances == num_edges(cpy));
- BOOST_CHECK((verify_isomorphism
- (g, make_filtered_graph(cpy, ignore_edges(u,v,cpy)),
- iso_map)));
- }
-
- void test_remove_edge(edge_t e, Graph& g)
- {
- Graph cpy;
- std::vector<vertex_t> iso_vec(num_vertices(g));
- IsoMap iso_map(iso_vec.begin(), get(vertex_index, g));
- copy_graph(g, cpy, orig_to_copy(iso_map));
-
- vertex_t u = source(e, g), v = target(e, g);
- deg_size_t occurances = count(adjacent_vertices(u, g), v);
-
- remove_edge(e, g);
-
- BOOST_CHECK(num_edges(g) + 1 == num_edges(cpy));
- BOOST_CHECK(count(adjacent_vertices(u, g), v) + 1 == occurances);
- BOOST_CHECK((verify_isomorphism
- (g, make_filtered_graph(cpy, ignore_edge(e)),
- iso_map)));
- }
-
- void test_clear_vertex(vertex_t v, Graph& g)
- {
- Graph cpy;
- std::vector<vertex_t> iso_vec(num_vertices(g));
- IsoMap iso_map(iso_vec.begin(), get(vertex_index, g));
- copy_graph(g, cpy, orig_to_copy(iso_map));
-
- clear_vertex(v, g);
-
- BOOST_CHECK(out_degree(v, g) == 0);
- BOOST_CHECK(num_vertices(g) == num_vertices(cpy));
- BOOST_CHECK((verify_isomorphism
- (g, make_filtered_graph(cpy, keep_all(), ignore_vertex(v)),
- iso_map)));
- }
-
- //=========================================================================
- // Property Map
-
- template <typename PropVal, typename PropertyTag>
- void test_readable_vertex_property_graph
- (const std::vector<PropVal>& vertex_prop, PropertyTag tag, const Graph& g)
- {
- typedef typename property_map<Graph, PropertyTag>::const_type const_Map;
- const_Map pmap = get(tag, g);
- typename std::vector<PropVal>::const_iterator i = vertex_prop.begin();
-
- for (typename boost::graph_traits<Graph>::vertex_iterator
- bgl_first_9 = vertices(g).first, bgl_last_9 = vertices(g).second;
- bgl_first_9 != bgl_last_9; bgl_first_9 = bgl_last_9)
- for (typename boost::graph_traits<Graph>::vertex_descriptor v;
- bgl_first_9 != bgl_last_9 ? (v = *bgl_first_9, true) : false;
- ++bgl_first_9) {
- //BGL_FORALL_VERTICES_T(v, g, Graph) {
- typename property_traits<const_Map>::value_type
- pval1 = get(pmap, v), pval2 = get(tag, g, v);
- BOOST_CHECK(pval1 == pval2);
- BOOST_CHECK(pval1 == *i++);
- }
- }
-
- template <typename PropVal, typename PropertyTag>
- void test_vertex_property_graph
- (const std::vector<PropVal>& vertex_prop, PropertyTag tag, Graph& g)
- {
- typedef typename property_map<Graph, PropertyTag>::type PMap;
- PMap pmap = get(tag, g);
- typename std::vector<PropVal>::const_iterator i = vertex_prop.begin();
- for (typename boost::graph_traits<Graph>::vertex_iterator
- bgl_first_9 = vertices(g).first, bgl_last_9 = vertices(g).second;
- bgl_first_9 != bgl_last_9; bgl_first_9 = bgl_last_9)
- for (typename boost::graph_traits<Graph>::vertex_descriptor v;
- bgl_first_9 != bgl_last_9 ? (v = *bgl_first_9, true) : false;
- ++bgl_first_9)
- // BGL_FORALL_VERTICES_T(v, g, Graph)
- put(pmap, v, *i++);
-
- test_readable_vertex_property_graph(vertex_prop, tag, g);
-
- BGL_FORALL_VERTICES_T(v, g, Graph)
- put(pmap, v, vertex_prop[0]);
-
- typename std::vector<PropVal>::const_iterator j = vertex_prop.begin();
- BGL_FORALL_VERTICES_T(v, g, Graph)
- put(tag, g, v, *j++);
-
- test_readable_vertex_property_graph(vertex_prop, tag, g);
- }
-
-
- };
-
-
-} // namespace boost
-
-#include <boost/graph/iteration_macros_undef.hpp>
-
-#endif // BOOST_GRAPH_TEST_HPP
diff --git a/boost/graph/graphml.hpp b/boost/graph/graphml.hpp
index a7faa647bb..9d798520ce 100644
--- a/boost/graph/graphml.hpp
+++ b/boost/graph/graphml.hpp
@@ -34,7 +34,7 @@ namespace boost
/////////////////////////////////////////////////////////////////////////////
// Graph reader exceptions
/////////////////////////////////////////////////////////////////////////////
-struct parse_error: public graph_exception
+struct BOOST_SYMBOL_VISIBLE parse_error: public graph_exception
{
parse_error(const std::string& err) {error = err; statement = "parse error: " + error;}
virtual ~parse_error() throw() {}
@@ -100,7 +100,7 @@ class mutate_graph_impl : public mutate_graph
mpl::for_each<value_types>(put_property<MutableGraph *,value_types>
(name, m_dp, &m_g, value, value_type, m_type_names, type_found));
}
- catch (bad_lexical_cast)
+ catch (const bad_lexical_cast&)
{
BOOST_THROW_EXCEPTION(
parse_error("invalid value \"" + value + "\" for key " +
@@ -125,7 +125,7 @@ class mutate_graph_impl : public mutate_graph
(name, m_dp, any_cast<vertex_descriptor>(vertex),
value, value_type, m_type_names, type_found));
}
- catch (bad_lexical_cast)
+ catch (const bad_lexical_cast&)
{
BOOST_THROW_EXCEPTION(
parse_error("invalid value \"" + value + "\" for key " +
@@ -150,7 +150,7 @@ class mutate_graph_impl : public mutate_graph
(name, m_dp, any_cast<edge_descriptor>(edge),
value, value_type, m_type_names, type_found));
}
- catch (bad_lexical_cast)
+ catch (const bad_lexical_cast&)
{
BOOST_THROW_EXCEPTION(
parse_error("invalid value \"" + value + "\" for key " +
diff --git a/boost/graph/graphviz.hpp b/boost/graph/graphviz.hpp
index 1c8cb194ac..b82e11a926 100644
--- a/boost/graph/graphviz.hpp
+++ b/boost/graph/graphviz.hpp
@@ -27,6 +27,7 @@
#include <boost/graph/dll_import_export.hpp>
#include <boost/graph/compressed_sparse_row_graph.hpp>
#include <boost/graph/iteration_macros.hpp>
+#include <boost/graph/detail/mpi_include.hpp>
#include <boost/spirit/include/classic_multi_pass.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/static_assert.hpp>
@@ -616,12 +617,12 @@ namespace boost {
/////////////////////////////////////////////////////////////////////////////
// Graph reader exceptions
/////////////////////////////////////////////////////////////////////////////
-struct graph_exception : public std::exception {
+struct BOOST_SYMBOL_VISIBLE graph_exception : public std::exception {
virtual ~graph_exception() throw() {}
virtual const char* what() const throw() = 0;
};
-struct bad_parallel_edge : public graph_exception {
+struct BOOST_SYMBOL_VISIBLE bad_parallel_edge : public graph_exception {
std::string from;
std::string to;
mutable std::string statement;
@@ -639,7 +640,7 @@ struct bad_parallel_edge : public graph_exception {
}
};
-struct directed_graph_error : public graph_exception {
+struct BOOST_SYMBOL_VISIBLE directed_graph_error : public graph_exception {
virtual ~directed_graph_error() throw() {}
virtual const char* what() const throw() {
return
@@ -648,7 +649,7 @@ struct directed_graph_error : public graph_exception {
}
};
-struct undirected_graph_error : public graph_exception {
+struct BOOST_SYMBOL_VISIBLE undirected_graph_error : public graph_exception {
virtual ~undirected_graph_error() throw() {}
virtual const char* what() const throw() {
return
@@ -657,7 +658,7 @@ struct undirected_graph_error : public graph_exception {
}
};
-struct bad_graphviz_syntax: public graph_exception {
+struct BOOST_SYMBOL_VISIBLE bad_graphviz_syntax: public graph_exception {
std::string errmsg;
bad_graphviz_syntax(const std::string& errmsg)
: errmsg(errmsg) {}
@@ -951,8 +952,6 @@ bool read_graphviz(std::istream& in, MutableGraph& graph,
} // namespace boost
-#ifdef BOOST_GRAPH_USE_MPI
-# include <boost/graph/distributed/graphviz.hpp>
-#endif
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/graphviz.hpp>)
#endif // BOOST_GRAPHVIZ_HPP
diff --git a/boost/graph/gursoy_atun_layout.hpp b/boost/graph/gursoy_atun_layout.hpp
index d843db7ac3..5ac52f30e1 100644
--- a/boost/graph/gursoy_atun_layout.hpp
+++ b/boost/graph/gursoy_atun_layout.hpp
@@ -14,7 +14,7 @@
// "Neighbourhood Preserving Load Balancing: A Self-Organizing Approach"
// in 6th International Euro-Par Conference Munich, Germany, August 29 – September 1, 2000 Proceedings,
// pp 234-241
-// http://dx.doi.org/10.1007/3-540-44520-X_32
+// https://doi.org/10.1007/3-540-44520-X_32
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/throw_exception.hpp>
@@ -183,7 +183,7 @@ gursoy_atun_step
typedef detail::gursoy_shortest<EdgeWeightMap> shortest;
shortest::run(graph, min_distance_loc, node_distance, update_position,
weight);
- } catch (detail::over_distance_limit) {
+ } catch (const detail::over_distance_limit&) {
/* Thrown to break out of BFS or Dijkstra early */
}
}
diff --git a/boost/graph/isomorphism.hpp b/boost/graph/isomorphism.hpp
index 225cd20513..cf70834aa6 100644
--- a/boost/graph/isomorphism.hpp
+++ b/boost/graph/isomorphism.hpp
@@ -501,6 +501,7 @@ fi_adj_loop_k:++fi_adj.first;
template <typename Graph1, typename Graph2>
struct isomorphism_impl {
typedef bool result_type;
+ typedef result_type type;
template <typename ArgPack>
bool operator()(const Graph1& g1, const Graph2& g2, const ArgPack& arg_pack) const {
using namespace boost::graph::keywords;
diff --git a/boost/graph/loop_erased_random_walk.hpp b/boost/graph/loop_erased_random_walk.hpp
index 712c45d7ca..5805c2e5bc 100644
--- a/boost/graph/loop_erased_random_walk.hpp
+++ b/boost/graph/loop_erased_random_walk.hpp
@@ -19,7 +19,7 @@
namespace boost {
- struct loop_erased_random_walk_stuck : public std::exception {
+ struct BOOST_SYMBOL_VISIBLE loop_erased_random_walk_stuck : public std::exception {
virtual ~loop_erased_random_walk_stuck() throw() {}
inline virtual const char* what() const throw() {
return "Loop-erased random walk found a vertex with no out-edges";
diff --git a/boost/graph/matrix_as_graph.hpp b/boost/graph/matrix_as_graph.hpp
index fb727940d7..4e8d56b921 100644
--- a/boost/graph/matrix_as_graph.hpp
+++ b/boost/graph/matrix_as_graph.hpp
@@ -12,6 +12,8 @@
#define BOOST_GRAPH_MATRIX2GRAPH_HPP
#include <utility>
+#include <cstddef>
+#include <iterator>
#include <boost/config.hpp>
#include <boost/operators.hpp>
#include <boost/pending/detail/int_iterator.hpp>
@@ -86,10 +88,14 @@ namespace boost {
template <class Iter, class Vertex>
class matrix_adj_iterator
- : public std::iterator<std::input_iterator_tag, Vertex >
{
typedef matrix_adj_iterator self;
public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef Vertex value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef Vertex* pointer;
+ typedef Vertex& reference;
matrix_adj_iterator() { }
matrix_adj_iterator(Iter i) : _iter(i) { }
matrix_adj_iterator(const self& x) : _iter(x._iter) { }
@@ -105,10 +111,14 @@ namespace boost {
template <class Iter, class Vertex>
class matrix_incidence_iterator
- : public std::iterator<std::input_iterator_tag, Iter >
{
typedef matrix_incidence_iterator self;
public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef Iter value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef Iter* pointer;
+ typedef Iter& reference;
matrix_incidence_iterator() { }
matrix_incidence_iterator(Iter i) : _iter(i) { }
matrix_incidence_iterator(const self& x) : _iter(x._iter) { }
diff --git a/boost/graph/max_cardinality_matching.hpp b/boost/graph/max_cardinality_matching.hpp
index 1549345a2f..5b4a8b70d6 100644
--- a/boost/graph/max_cardinality_matching.hpp
+++ b/boost/graph/max_cardinality_matching.hpp
@@ -27,7 +27,7 @@
namespace boost
{
namespace graph { namespace detail {
- enum { V_EVEN, V_ODD, V_UNREACHED };
+ enum VERTEX_STATE { V_EVEN, V_ODD, V_UNREACHED };
} } // end namespace graph::detail
template <typename Graph, typename MateMap, typename VertexIndexMap>
diff --git a/boost/graph/maximum_adjacency_search.hpp b/boost/graph/maximum_adjacency_search.hpp
index e27a7a048e..211bf7ee84 100644
--- a/boost/graph/maximum_adjacency_search.hpp
+++ b/boost/graph/maximum_adjacency_search.hpp
@@ -146,10 +146,10 @@ namespace boost {
// start traversing the graph
//vertex_descriptor s, t;
- weight_type w;
+ //weight_type w;
while (!pq.empty()) { // while PQ \neq {} do
const vertex_descriptor u = pq.top(); // u = extractmax(PQ)
- w = get(keys, u); vis.start_vertex(u, g);
+ /* weight_type w = */ get(keys, u); vis.start_vertex(u, g);
pq.pop(); // vis.start_vertex(u, g);
BGL_FORALL_OUTEDGES_T(u, e, g, Graph) { // foreach (u, v) \in E do
@@ -218,9 +218,9 @@ maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, cons
struct mas_dispatch {
typedef void result_type;
template <typename Graph, typename ArgPack>
- static result_type apply(const Graph& g,
- //const bgl_named_params<P,T,R>& params,
- const ArgPack& params,
+ static result_type apply(const Graph& g,
+ //const bgl_named_params<P,T,R>& params,
+ const ArgPack& params,
WeightMap w) {
using namespace boost::graph::keywords;
@@ -233,12 +233,25 @@ maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, cons
typename boost::result_of<default_pq_gen_type(const Graph&, const ArgPack&)>::type pq = pq_gen(g, params);
+ boost::null_visitor null_vis;
+ boost::mas_visitor<boost::null_visitor> default_visitor(null_vis);
+ vertex_descriptor v = vertex_descriptor();
+ boost::detail::make_property_map_from_arg_pack_gen<
+ boost::graph::keywords::tag::vertex_assignment_map,
+ vertex_descriptor
+ > map_gen(v);
+ typename boost::detail::map_maker<
+ Graph,
+ ArgPack,
+ boost::graph::keywords::tag::vertex_assignment_map,
+ vertex_descriptor
+ >::map_type default_map = map_gen(g, params);
boost::maximum_adjacency_search
(g,
w,
- params [ _visitor | make_mas_visitor(null_visitor())],
+ params [ _visitor | default_visitor],
params [ _root_vertex | *vertices(g).first],
- params [ _vertex_assignment_map | boost::detail::make_property_map_from_arg_pack_gen<boost::graph::keywords::tag::vertex_assignment_map, vertex_descriptor>(vertex_descriptor())(g, params)],
+ params [ _vertex_assignment_map | default_map],
pq
);
}
@@ -249,8 +262,8 @@ maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, cons
typedef void result_type;
template <typename Graph, typename ArgPack>
- static result_type apply(const Graph& g,
- const ArgPack& params,
+ static result_type apply(const Graph& g,
+ const ArgPack& params,
param_not_found) {
using namespace boost::graph::keywords;
@@ -266,12 +279,25 @@ maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, cons
typename boost::result_of<default_pq_gen_type(const Graph&, const ArgPack&)>::type pq = pq_gen(g, params);
+ boost::null_visitor null_vis;
+ boost::mas_visitor<boost::null_visitor> default_visitor(null_vis);
+ vertex_descriptor v = vertex_descriptor();
+ boost::detail::make_property_map_from_arg_pack_gen<
+ boost::graph::keywords::tag::vertex_assignment_map,
+ vertex_descriptor
+ > map_gen(v);
+ typename boost::detail::map_maker<
+ Graph,
+ ArgPack,
+ boost::graph::keywords::tag::vertex_assignment_map,
+ vertex_descriptor
+ >::map_type default_map = map_gen(g, params);
boost::maximum_adjacency_search
(g,
get(edge_weight, g),
- params [ _visitor | make_mas_visitor(null_visitor())],
+ params [ _visitor | default_visitor],
params [ _root_vertex | *vertices(g).first],
- params [ _vertex_assignment_map | boost::detail::make_property_map_from_arg_pack_gen<boost::graph::keywords::tag::vertex_assignment_map, vertex_descriptor>(vertex_descriptor())(g, params)],
+ params [ _vertex_assignment_map | default_map],
pq
);
}
diff --git a/boost/graph/maximum_weighted_matching.hpp b/boost/graph/maximum_weighted_matching.hpp
new file mode 100644
index 0000000000..6fbc4dd422
--- /dev/null
+++ b/boost/graph/maximum_weighted_matching.hpp
@@ -0,0 +1,1167 @@
+//=======================================================================
+// Copyright (c) 2018 Yi Ji
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+//=======================================================================
+
+#ifndef BOOST_GRAPH_MAXIMUM_WEIGHTED_MATCHING_HPP
+#define BOOST_GRAPH_MAXIMUM_WEIGHTED_MATCHING_HPP
+
+#include <algorithm> // for std::iter_swap
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/graph/max_cardinality_matching.hpp>
+
+namespace boost
+{
+ template <typename Graph, typename MateMap, typename VertexIndexMap>
+ typename property_traits<typename property_map<Graph, edge_weight_t>::type>::value_type
+ matching_weight_sum(const Graph& g, MateMap mate, VertexIndexMap vm)
+ {
+ typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor_t;
+ typedef typename property_traits<typename property_map<Graph, edge_weight_t>::type>::value_type edge_property_t;
+
+ edge_property_t weight_sum = 0;
+ vertex_iterator_t vi, vi_end;
+
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ {
+ vertex_descriptor_t v = *vi;
+ if (get(mate, v) != graph_traits<Graph>::null_vertex() && get(vm, v) < get(vm, get(mate,v)))
+ weight_sum += get(edge_weight, g, edge(v,mate[v],g).first);
+ }
+ return weight_sum;
+ }
+
+ template <typename Graph, typename MateMap>
+ inline typename property_traits<typename property_map<Graph, edge_weight_t>::type>::value_type
+ matching_weight_sum(const Graph& g, MateMap mate)
+ {
+ return matching_weight_sum(g, mate, get(vertex_index,g));
+ }
+
+ template <typename Graph, typename MateMap, typename VertexIndexMap>
+ class weighted_augmenting_path_finder
+ {
+ public:
+
+ template <typename T>
+ struct map_vertex_to_
+ {
+ typedef boost::iterator_property_map<typename std::vector<T>::iterator, VertexIndexMap> type;
+ };
+ typedef typename graph::detail::VERTEX_STATE vertex_state_t;
+ typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor_t;
+ typedef typename std::vector<vertex_descriptor_t>::const_iterator vertex_vec_iter_t;
+ typedef typename graph_traits<Graph>::out_edge_iterator out_edge_iterator_t;
+ typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor_t;
+ typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
+ typedef typename property_traits<typename property_map<Graph, edge_weight_t>::type>::value_type edge_property_t;
+ typedef std::deque<vertex_descriptor_t> vertex_list_t;
+ typedef std::vector<edge_descriptor_t> edge_list_t;
+ typedef typename map_vertex_to_<vertex_descriptor_t>::type vertex_to_vertex_map_t;
+ typedef typename map_vertex_to_<edge_property_t>::type vertex_to_weight_map_t;
+ typedef typename map_vertex_to_<bool>::type vertex_to_bool_map_t;
+ typedef typename map_vertex_to_<std::pair<vertex_descriptor_t, vertex_descriptor_t> >::type vertex_to_pair_map_t;
+ typedef typename map_vertex_to_<std::pair<edge_descriptor_t, bool> >::type vertex_to_edge_map_t;
+ typedef typename map_vertex_to_<vertex_to_edge_map_t>::type vertex_pair_to_edge_map_t;
+
+ class blossom
+ {
+ public:
+
+ typedef boost::shared_ptr<blossom> blossom_ptr_t;
+ std::vector<blossom_ptr_t> sub_blossoms;
+ edge_property_t dual_var;
+ blossom_ptr_t father;
+
+ blossom() : dual_var(0), father(blossom_ptr_t()) {}
+
+ // get the base vertex of a blossom by recursively getting
+ // its base sub-blossom, which is always the first one in
+ // sub_blossoms because of how we create and maintain blossoms
+ virtual vertex_descriptor_t get_base() const
+ {
+ const blossom* b = this;
+ while (!b->sub_blossoms.empty())
+ b = b->sub_blossoms[0].get();
+ return b->get_base();
+ }
+
+ // set a sub-blossom as a blossom's base by exchanging it
+ // with its first sub-blossom
+ void set_base(const blossom_ptr_t& sub)
+ {
+ for (blossom_iterator_t bi = sub_blossoms.begin(); bi != sub_blossoms.end(); ++bi)
+ {
+ if (sub.get() == bi->get())
+ {
+ std::iter_swap(sub_blossoms.begin(), bi);
+ break;
+ }
+ }
+ }
+
+ // get all vertices inside recursively
+ virtual std::vector<vertex_descriptor_t> vertices() const
+ {
+ std::vector<vertex_descriptor_t> all_vertices;
+ for (typename std::vector<blossom_ptr_t>::const_iterator bi = sub_blossoms.begin(); bi != sub_blossoms.end(); ++bi)
+ {
+ std::vector<vertex_descriptor_t> some_vertices = (*bi)->vertices();
+ all_vertices.insert(all_vertices.end(), some_vertices.begin(), some_vertices.end());
+ }
+ return all_vertices;
+ }
+ };
+
+ // a trivial_blossom only has one vertex and no sub-blossom;
+ // for each vertex v, in_blossom[v] is the trivial_blossom that contains it directly
+ class trivial_blossom : public blossom
+ {
+ public:
+ trivial_blossom(vertex_descriptor_t v) : trivial_vertex(v) {}
+ virtual vertex_descriptor_t get_base() const
+ {
+ return trivial_vertex;
+ }
+
+ virtual std::vector<vertex_descriptor_t> vertices() const
+ {
+ std::vector<vertex_descriptor_t> all_vertices;
+ all_vertices.push_back(trivial_vertex);
+ return all_vertices;
+ }
+
+ private:
+
+ vertex_descriptor_t trivial_vertex;
+ };
+
+ typedef boost::shared_ptr<blossom> blossom_ptr_t;
+ typedef typename std::vector<blossom_ptr_t>::iterator blossom_iterator_t;
+ typedef typename map_vertex_to_<blossom_ptr_t>::type vertex_to_blossom_map_t;
+
+ weighted_augmenting_path_finder(const Graph& arg_g, MateMap arg_mate, VertexIndexMap arg_vm) :
+ g(arg_g),
+ vm(arg_vm),
+ null_edge(std::pair<edge_descriptor_t, bool>(num_edges(g) == 0 ? edge_descriptor_t() : *edges(g).first, false)),
+ mate_vector(num_vertices(g)),
+ label_S_vector(num_vertices(g), graph_traits<Graph>::null_vertex()),
+ label_T_vector(num_vertices(g), graph_traits<Graph>::null_vertex()),
+ outlet_vector(num_vertices(g), graph_traits<Graph>::null_vertex()),
+ tau_idx_vector(num_vertices(g), graph_traits<Graph>::null_vertex()),
+ dual_var_vector(std::vector<edge_property_t>(num_vertices(g), std::numeric_limits<edge_property_t>::min())),
+ pi_vector(std::vector<edge_property_t>(num_vertices(g), std::numeric_limits<edge_property_t>::max())),
+ gamma_vector(std::vector<edge_property_t>(num_vertices(g), std::numeric_limits<edge_property_t>::max())),
+ tau_vector(std::vector<edge_property_t>(num_vertices(g), std::numeric_limits<edge_property_t>::max())),
+ in_blossom_vector(num_vertices(g)),
+ old_label_vector(num_vertices(g)),
+ critical_edge_vectors(num_vertices(g), std::vector<std::pair<edge_descriptor_t, bool> >(num_vertices(g), null_edge)),
+
+ mate(mate_vector.begin(), vm),
+ label_S(label_S_vector.begin(), vm),
+ label_T(label_T_vector.begin(), vm),
+ outlet(outlet_vector.begin(), vm),
+ tau_idx(tau_idx_vector.begin(), vm),
+ dual_var(dual_var_vector.begin(), vm),
+ pi(pi_vector.begin(), vm),
+ gamma(gamma_vector.begin(), vm),
+ tau(tau_vector.begin(), vm),
+ in_blossom(in_blossom_vector.begin(), vm),
+ old_label(old_label_vector.begin(), vm)
+ {
+ vertex_iterator_t vi, vi_end;
+ edge_iterator_t ei, ei_end;
+
+ edge_property_t max_weight = std::numeric_limits<edge_property_t>::min();
+ for (boost::tie(ei,ei_end) = edges(g); ei != ei_end; ++ei)
+ max_weight = std::max(max_weight, get(edge_weight, g, *ei));
+
+ typename std::vector<std::vector<std::pair<edge_descriptor_t, bool> > >::iterator vei;
+
+ for (boost::tie(vi,vi_end) = vertices(g), vei = critical_edge_vectors.begin(); vi != vi_end; ++vi, ++vei)
+ {
+ vertex_descriptor_t u = *vi;
+ mate[u] = get(arg_mate, u);
+ dual_var[u] = 2*max_weight;
+ in_blossom[u] = boost::make_shared<trivial_blossom>(u);
+ outlet[u] = u;
+ critical_edge_vector.push_back(vertex_to_edge_map_t(vei->begin(), vm));
+ }
+
+ critical_edge = vertex_pair_to_edge_map_t(critical_edge_vector.begin(), vm);
+
+ init();
+ }
+
+ // return the top blossom where v is contained inside
+ blossom_ptr_t in_top_blossom(vertex_descriptor_t v) const
+ {
+ blossom_ptr_t b = in_blossom[v];
+ while (b->father != blossom_ptr_t())
+ b = b->father;
+ return b;
+ }
+
+ // check if vertex v is in blossom b
+ bool is_in_blossom(blossom_ptr_t b, vertex_descriptor_t v) const
+ {
+ if (v == graph_traits<Graph>::null_vertex())
+ return false;
+ blossom_ptr_t vb = in_blossom[v]->father;
+ while (vb != blossom_ptr_t())
+ {
+ if (vb.get() == b.get())
+ return true;
+ vb = vb->father;
+ }
+ return false;
+ }
+
+ // return the base vertex of the top blossom that contains v
+ inline vertex_descriptor_t base_vertex(vertex_descriptor_t v) const
+ {
+ return in_top_blossom(v)->get_base();
+ }
+
+ // add an existed top blossom of base vertex v into new top
+ // blossom b as its sub-blossom
+ void add_sub_blossom(blossom_ptr_t b, vertex_descriptor_t v)
+ {
+ blossom_ptr_t sub = in_top_blossom(v);
+ sub->father = b;
+ b->sub_blossoms.push_back(sub);
+ if (sub->sub_blossoms.empty())
+ return;
+ for (blossom_iterator_t bi = top_blossoms.begin(); bi != top_blossoms.end(); ++bi)
+ {
+ if (bi->get() == sub.get())
+ {
+ top_blossoms.erase(bi);
+ break;
+ }
+ }
+ }
+
+ // when a top blossom is created or its base vertex getting an S-label,
+ // add all edges incident to this blossom into even_edges
+ void bloom(blossom_ptr_t b)
+ {
+ std::vector<vertex_descriptor_t> vertices_of_b = b->vertices();
+ vertex_vec_iter_t vi;
+ for (vi = vertices_of_b.begin(); vi != vertices_of_b.end(); ++vi)
+ {
+ out_edge_iterator_t oei, oei_end;
+ for (boost::tie(oei,oei_end) = out_edges(*vi, g); oei != oei_end; ++oei)
+ {
+ if (target(*oei,g) != *vi && mate[*vi] != target(*oei,g))
+ even_edges.push_back(*oei);
+ }
+ }
+ }
+
+ // assigning a T-label to a non S-vertex, along with outlet and updating pi value
+ // if updated pi[v] equals zero, augment the matching from its mate vertex
+ void put_T_label(vertex_descriptor_t v, vertex_descriptor_t T_label,
+ vertex_descriptor_t outlet_v, edge_property_t pi_v)
+ {
+ if (label_S[v] != graph_traits<Graph>::null_vertex())
+ return;
+
+ label_T[v] = T_label;
+ outlet[v] = outlet_v;
+ pi[v] = pi_v;
+
+ vertex_descriptor_t v_mate = mate[v];
+ if (pi[v] == 0)
+ {
+ label_T[v_mate] = graph_traits<Graph>::null_vertex();
+ label_S[v_mate] = v;
+ bloom(in_top_blossom(v_mate));
+ }
+ }
+
+ // get the missing T-label for a to-be-expanded base vertex
+ // the missing T-label is the last vertex of the path from outlet[v] to v
+ std::pair<vertex_descriptor_t, vertex_descriptor_t> missing_label(vertex_descriptor_t b_base)
+ {
+ vertex_descriptor_t missing_outlet = outlet[b_base];
+
+ if (outlet[b_base] == b_base)
+ return std::make_pair(graph_traits<Graph>::null_vertex(), missing_outlet);
+
+ vertex_iterator_t vi, vi_end;
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ old_label[*vi] = std::make_pair(label_T[*vi], outlet[*vi]);
+
+ std::pair<vertex_descriptor_t, vertex_state_t> child(outlet[b_base], graph::detail::V_EVEN);
+ blossom_ptr_t b = in_blossom[child.first];
+ for (; b->father->father != blossom_ptr_t(); b = b->father);
+ child.first = b->get_base();
+
+ if (child.first == b_base)
+ return std::make_pair(graph_traits<Graph>::null_vertex(), missing_outlet);
+
+ while (true)
+ {
+ std::pair<vertex_descriptor_t, vertex_state_t> child_parent = parent(child, true);
+
+ for (b = in_blossom[child_parent.first]; b->father->father != blossom_ptr_t(); b = b->father);
+ missing_outlet = child_parent.first;
+ child_parent.first = b->get_base();
+
+ if (child_parent.first == b_base)
+ break;
+ else
+ child = child_parent;
+ }
+ return std::make_pair(child.first, missing_outlet);
+ }
+
+ // expand a top blossom, put all its non-trivial sub-blossoms into top_blossoms
+ blossom_iterator_t expand_blossom(blossom_iterator_t bi, std::vector<blossom_ptr_t>& new_ones)
+ {
+ blossom_ptr_t b = *bi;
+ for (blossom_iterator_t i = b->sub_blossoms.begin(); i != b->sub_blossoms.end(); ++i)
+ {
+ blossom_ptr_t sub_blossom = *i;
+ vertex_descriptor_t sub_base = sub_blossom->get_base();
+ label_S[sub_base] = label_T[sub_base] = graph_traits<Graph>::null_vertex();
+ outlet[sub_base] = sub_base;
+ sub_blossom->father = blossom_ptr_t();
+ // new top blossoms cannot be pushed back into top_blossoms immediately,
+ // because push_back() may cause reallocation and then invalid iterators
+ if (!sub_blossom->sub_blossoms.empty())
+ new_ones.push_back(sub_blossom);
+ }
+ return top_blossoms.erase(bi);
+ }
+
+ // when expanding a T-blossom with base v, it requires more operations:
+ // supply the missing T-labels for new base vertices by picking the minimum tau from vertices of
+ // each corresponding new top-blossoms; when label_T[v] is null or we have a smaller tau from
+ // missing_label(v), replace T-label and outlet of v (but don't bloom v)
+ blossom_iterator_t expand_T_blossom(blossom_iterator_t bi, std::vector<blossom_ptr_t>& new_ones)
+ {
+ blossom_ptr_t b = *bi;
+
+ vertex_descriptor_t b_base = b->get_base();
+ std::pair<vertex_descriptor_t, vertex_descriptor_t> T_and_outlet = missing_label(b_base);
+
+ blossom_iterator_t next_bi = expand_blossom(bi, new_ones);
+
+ for (blossom_iterator_t i = b->sub_blossoms.begin(); i != b->sub_blossoms.end(); ++i)
+ {
+ blossom_ptr_t sub_blossom = *i;
+ vertex_descriptor_t sub_base = sub_blossom->get_base();
+ vertex_descriptor_t min_tau_v = graph_traits<Graph>::null_vertex();
+ edge_property_t min_tau = std::numeric_limits<edge_property_t>::max();
+
+ std::vector<vertex_descriptor_t> sub_vertices = sub_blossom->vertices();
+ for (vertex_vec_iter_t v = sub_vertices.begin(); v != sub_vertices.end(); ++v)
+ {
+ if (tau[*v] < min_tau)
+ {
+ min_tau = tau[*v];
+ min_tau_v = *v;
+ }
+ }
+
+ if (min_tau < std::numeric_limits<edge_property_t>::max())
+ put_T_label(sub_base, tau_idx[min_tau_v], min_tau_v, tau[min_tau_v]);
+ }
+
+ if (label_T[b_base] == graph_traits<Graph>::null_vertex() || tau[old_label[b_base].second] < pi[b_base])
+ boost::tie(label_T[b_base], outlet[b_base]) = T_and_outlet;
+
+ return next_bi;
+ }
+
+ // when vertices v and w are matched to each other by augmenting,
+ // we must set v/w as base vertex of any blossom who contains v/w and
+ // is a sub-blossom of their lowest (smallest) common blossom
+ void adjust_blossom(vertex_descriptor_t v, vertex_descriptor_t w)
+ {
+ blossom_ptr_t vb = in_blossom[v], wb = in_blossom[w], lowest_common_blossom;
+ std::vector<blossom_ptr_t> v_ancestors, w_ancestors;
+
+ while (vb->father != blossom_ptr_t())
+ {
+ v_ancestors.push_back(vb->father);
+ vb = vb->father;
+ }
+ while (wb->father != blossom_ptr_t())
+ {
+ w_ancestors.push_back(wb->father);
+ wb = wb->father;
+ }
+
+ typename std::vector<blossom_ptr_t>::reverse_iterator i, j;
+ i = v_ancestors.rbegin();
+ j = w_ancestors.rbegin();
+ while (i != v_ancestors.rend() && j != w_ancestors.rend() && i->get() == j->get())
+ {
+ lowest_common_blossom = *i;
+ ++i;++j;
+ }
+
+ vb = in_blossom[v];
+ wb = in_blossom[w];
+ while (vb->father != lowest_common_blossom)
+ {
+ vb->father->set_base(vb);
+ vb = vb->father;
+ }
+ while (wb->father != lowest_common_blossom)
+ {
+ wb->father->set_base(wb);
+ wb = wb->father;
+ }
+ }
+
+ // every edge weight is multiplied by 4 to ensure integer weights
+ // throughout the algorithm if all input weights are integers
+ inline edge_property_t slack(const edge_descriptor_t& e) const
+ {
+ vertex_descriptor_t v, w;
+ v = source(e, g);
+ w = target(e, g);
+ return dual_var[v] + dual_var[w] - 4*get(edge_weight, g, e);
+ }
+
+ // backtrace one step on vertex v along the augmenting path
+ // by its labels and its vertex state;
+ // boolean parameter "use_old" means whether we are updating labels,
+ // if we are, then we use old labels to backtrace and also we
+ // don't jump to its base vertex when we reach an odd vertex
+ std::pair<vertex_descriptor_t, vertex_state_t> parent(std::pair<vertex_descriptor_t, vertex_state_t> v,
+ bool use_old = false) const
+ {
+ if (v.second == graph::detail::V_EVEN)
+ {
+ // a paranoid check: label_S shoule be the same as mate in backtracing
+ if (label_S[v.first] == graph_traits<Graph>::null_vertex())
+ label_S[v.first] = mate[v.first];
+ return std::make_pair(label_S[v.first], graph::detail::V_ODD);
+ }
+ else if (v.second == graph::detail::V_ODD)
+ {
+ vertex_descriptor_t w = use_old ? old_label[v.first].first : base_vertex(label_T[v.first]);
+ return std::make_pair(w, graph::detail::V_EVEN);
+ }
+ return std::make_pair(v.first, graph::detail::V_UNREACHED);
+ }
+
+ // backtrace from vertices v and w to their free (unmatched) ancesters,
+ // return the nearest common ancestor (null_vertex if none) of v and w
+ vertex_descriptor_t nearest_common_ancestor(vertex_descriptor_t v, vertex_descriptor_t w,
+ vertex_descriptor_t& v_free_ancestor,
+ vertex_descriptor_t& w_free_ancestor) const
+ {
+ std::pair<vertex_descriptor_t, vertex_state_t> v_up(v, graph::detail::V_EVEN);
+ std::pair<vertex_descriptor_t, vertex_state_t> w_up(w, graph::detail::V_EVEN);
+ vertex_descriptor_t nca;
+ nca = w_free_ancestor = v_free_ancestor = graph_traits<Graph>::null_vertex();
+
+ std::vector<bool> ancestor_of_w_vector(num_vertices(g), false);
+ std::vector<bool> ancestor_of_v_vector(num_vertices(g), false);
+ vertex_to_bool_map_t ancestor_of_w(ancestor_of_w_vector.begin(), vm);
+ vertex_to_bool_map_t ancestor_of_v(ancestor_of_v_vector.begin(), vm);
+
+ while (nca == graph_traits<Graph>::null_vertex() &&
+ (v_free_ancestor == graph_traits<Graph>::null_vertex() ||
+ w_free_ancestor == graph_traits<Graph>::null_vertex()))
+ {
+ ancestor_of_w[w_up.first] = true;
+ ancestor_of_v[v_up.first] = true;
+
+ if (w_free_ancestor == graph_traits<Graph>::null_vertex())
+ w_up = parent(w_up);
+ if (v_free_ancestor == graph_traits<Graph>::null_vertex())
+ v_up = parent(v_up);
+
+ if (mate[v_up.first] == graph_traits<Graph>::null_vertex())
+ v_free_ancestor = v_up.first;
+ if (mate[w_up.first] == graph_traits<Graph>::null_vertex())
+ w_free_ancestor = w_up.first;
+
+ if (ancestor_of_w[v_up.first] == true || v_up.first == w_up.first)
+ nca = v_up.first;
+ else if (ancestor_of_v[w_up.first] == true)
+ nca = w_up.first;
+ else if (v_free_ancestor == w_free_ancestor &&
+ v_free_ancestor != graph_traits<Graph>::null_vertex())
+ nca = v_up.first;
+ }
+
+ return nca;
+ }
+
+ // when a new top blossom b is created by connecting (v, w), we add sub-blossoms into
+ // b along backtracing from v_prime and w_prime to stop_vertex (the base vertex);
+ // also, we set labels and outlet for each base vertex we pass by
+ void make_blossom(blossom_ptr_t b, vertex_descriptor_t w_prime,
+ vertex_descriptor_t v_prime, vertex_descriptor_t stop_vertex)
+ {
+ std::pair<vertex_descriptor_t, vertex_state_t> u(v_prime, graph::detail::V_ODD);
+ std::pair<vertex_descriptor_t, vertex_state_t> u_up(w_prime, graph::detail::V_EVEN);
+
+ for (; u_up.first != stop_vertex; u = u_up, u_up = parent(u))
+ {
+ if (u_up.second == graph::detail::V_EVEN)
+ {
+ if (!in_top_blossom(u_up.first)->sub_blossoms.empty())
+ outlet[u_up.first] = label_T[u.first];
+ label_T[u_up.first] = outlet[u.first];
+ }
+ else if (u_up.second == graph::detail::V_ODD)
+ label_S[u_up.first] = u.first;
+
+ add_sub_blossom(b, u_up.first);
+ }
+ }
+
+ // the design of recursively expanding augmenting path in (reversed_)retrieve_augmenting_path
+ // functions is inspired by same functions in max_cardinality_matching.hpp;
+ // except that in weighted matching, we use "outlet" vertices instead of "bridge" vertex pairs:
+ // if blossom b is the smallest non-trivial blossom that contains its base vertex v, then
+ // v and outlet[v] are where augmenting path enters and leaves b
+ void retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w, vertex_state_t v_state)
+ {
+ if (v == w)
+ aug_path.push_back(v);
+ else if (v_state == graph::detail::V_EVEN)
+ {
+ aug_path.push_back(v);
+ retrieve_augmenting_path(label_S[v], w, graph::detail::V_ODD);
+ }
+ else if (v_state == graph::detail::V_ODD)
+ {
+ if (outlet[v] == v)
+ aug_path.push_back(v);
+ else
+ reversed_retrieve_augmenting_path(outlet[v], v, graph::detail::V_EVEN);
+ retrieve_augmenting_path(label_T[v], w, graph::detail::V_EVEN);
+ }
+ }
+
+ void reversed_retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w, vertex_state_t v_state)
+ {
+ if (v == w)
+ aug_path.push_back(v);
+ else if (v_state == graph::detail::V_EVEN)
+ {
+ reversed_retrieve_augmenting_path(label_S[v], w, graph::detail::V_ODD);
+ aug_path.push_back(v);
+ }
+ else if (v_state == graph::detail::V_ODD)
+ {
+ reversed_retrieve_augmenting_path(label_T[v], w, graph::detail::V_EVEN);
+ if (outlet[v] != v)
+ retrieve_augmenting_path(outlet[v], v, graph::detail::V_EVEN);
+ else
+ aug_path.push_back(v);
+ }
+ }
+
+ // correct labels for vertices in the augmenting path
+ void relabel(vertex_descriptor_t v)
+ {
+ blossom_ptr_t b = in_blossom[v]->father;
+
+ if (!is_in_blossom(b, mate[v]))
+ { // if v is a new base vertex
+ std::pair<vertex_descriptor_t, vertex_state_t> u(v, graph::detail::V_EVEN);
+ while (label_S[u.first] != u.first && is_in_blossom(b, label_S[u.first]))
+ u = parent(u, true);
+
+ vertex_descriptor_t old_base = u.first;
+ if (label_S[old_base] != old_base)
+ { // if old base is not exposed
+ label_T[v] = label_S[old_base];
+ outlet[v] = old_base;
+ }
+ else
+ { // if old base is exposed then new label_T[v] is not in b,
+ // we must (i) make b2 the smallest blossom containing v but not as base vertex
+ // (ii) backtrace from b2's new base vertex to b
+ label_T[v] = graph_traits<Graph>::null_vertex();
+ for (b = b->father; b != blossom_ptr_t() && b->get_base() == v; b = b->father);
+ if (b != blossom_ptr_t())
+ {
+ u = std::make_pair(b->get_base(), graph::detail::V_ODD);
+ while (!is_in_blossom(in_blossom[v]->father, old_label[u.first].first))
+ u = parent(u, true);
+ label_T[v] = u.first;
+ outlet[v] = old_label[u.first].first;
+ }
+ }
+ }
+ else if (label_S[v] == v || !is_in_blossom(b, label_S[v]))
+ { // if v is an old base vertex
+ // let u be the new base vertex; backtrace from u's old T-label
+ std::pair<vertex_descriptor_t, vertex_state_t> u(b->get_base(), graph::detail::V_ODD);
+ while (old_label[u.first].first != graph_traits<Graph>::null_vertex() && old_label[u.first].first != v)
+ u = parent(u, true);
+ label_T[v] = old_label[u.first].second;
+ outlet[v] = v;
+ }
+ else // if v is neither a new nor an old base vertex
+ label_T[v] = label_S[v];
+ }
+
+ void augmenting(vertex_descriptor_t v, vertex_descriptor_t v_free_ancestor,
+ vertex_descriptor_t w, vertex_descriptor_t w_free_ancestor)
+ {
+ vertex_iterator_t vi, vi_end;
+
+ // retrieve the augmenting path and put it in aug_path
+ reversed_retrieve_augmenting_path(v, v_free_ancestor, graph::detail::V_EVEN);
+ retrieve_augmenting_path(w, w_free_ancestor, graph::detail::V_EVEN);
+
+ // augment the matching along aug_path
+ vertex_descriptor_t a, b;
+ vertex_list_t reversed_aug_path;
+ while (!aug_path.empty())
+ {
+ a = aug_path.front();
+ aug_path.pop_front();
+ reversed_aug_path.push_back(a);
+ b = aug_path.front();
+ aug_path.pop_front();
+ reversed_aug_path.push_back(b);
+
+ mate[a] = b;
+ mate[b] = a;
+
+ // reset base vertex for every blossom in augment path
+ adjust_blossom(a, b);
+ }
+
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ old_label[*vi] = std::make_pair(label_T[*vi], outlet[*vi]);
+
+ // correct labels for in-blossom vertices along aug_path
+ while (!reversed_aug_path.empty())
+ {
+ a = reversed_aug_path.front();
+ reversed_aug_path.pop_front();
+
+ if (in_blossom[a]->father != blossom_ptr_t())
+ relabel(a);
+ }
+
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ {
+ vertex_descriptor_t u = *vi;
+ if (mate[u] != graph_traits<Graph>::null_vertex())
+ label_S[u] = mate[u];
+ }
+
+ // expand blossoms with zero dual variables
+ std::vector<blossom_ptr_t> new_top_blossoms;
+ for (blossom_iterator_t bi = top_blossoms.begin(); bi != top_blossoms.end();)
+ {
+ if ((*bi)->dual_var <= 0)
+ bi = expand_blossom(bi, new_top_blossoms);
+ else
+ ++bi;
+ }
+ top_blossoms.insert(top_blossoms.end(), new_top_blossoms.begin(), new_top_blossoms.end());
+ init();
+ }
+
+ // create a new blossom and set labels for vertices inside
+ void blossoming(vertex_descriptor_t v, vertex_descriptor_t v_prime,
+ vertex_descriptor_t w, vertex_descriptor_t w_prime,
+ vertex_descriptor_t nca)
+ {
+ vertex_iterator_t vi, vi_end;
+
+ std::vector<bool> is_old_base_vector(num_vertices(g));
+ vertex_to_bool_map_t is_old_base(is_old_base_vector.begin(), vm);
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ {
+ if (*vi == base_vertex(*vi))
+ is_old_base[*vi] = true;
+ }
+
+ blossom_ptr_t b = boost::make_shared<blossom>();
+ add_sub_blossom(b, nca);
+
+ label_T[w_prime] = v;
+ label_T[v_prime] = w;
+ outlet[w_prime] = w;
+ outlet[v_prime] = v;
+
+ make_blossom(b, w_prime, v_prime, nca);
+ make_blossom(b, v_prime, w_prime, nca);
+
+ label_T[nca] = graph_traits<Graph>::null_vertex();
+ outlet[nca] = nca;
+
+ top_blossoms.push_back(b);
+ bloom(b);
+
+ // set gamma[b_base] = min_slack{critical_edge(b_base, other_base)} where each critical edge
+ // is updated before, by argmin{slack(old_bases_in_b, other_base)};
+ vertex_vec_iter_t i, j;
+ std::vector<vertex_descriptor_t> b_vertices = b->vertices(), old_base_in_b, other_base;
+ vertex_descriptor_t b_base = b->get_base();
+ for (i = b_vertices.begin(); i != b_vertices.end(); ++i)
+ {
+ if (is_old_base[*i])
+ old_base_in_b.push_back(*i);
+ }
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ {
+ if (*vi != b_base && *vi == base_vertex(*vi))
+ other_base.push_back(*vi);
+ }
+ for (i = other_base.begin(); i != other_base.end(); ++i)
+ {
+ edge_property_t min_slack = std::numeric_limits<edge_property_t>::max();
+ std::pair<edge_descriptor_t, bool> b_vi = null_edge;
+ for (j = old_base_in_b.begin(); j != old_base_in_b.end(); ++j)
+ {
+ if (critical_edge[*j][*i] != null_edge && min_slack > slack(critical_edge[*j][*i].first))
+ {
+ min_slack = slack(critical_edge[*j][*i].first);
+ b_vi = critical_edge[*j][*i];
+ }
+ }
+ critical_edge[b_base][*i] = critical_edge[*i][b_base] = b_vi;
+ }
+ gamma[b_base] = std::numeric_limits<edge_property_t>::max();
+ for (i = other_base.begin(); i != other_base.end(); ++i)
+ {
+ if (critical_edge[b_base][*i] != null_edge)
+ gamma[b_base] = std::min(gamma[b_base], slack(critical_edge[b_base][*i].first));
+ }
+ }
+
+ void init()
+ {
+ even_edges.clear();
+
+ vertex_iterator_t vi, vi_end;
+ typename std::vector<std::vector<std::pair<edge_descriptor_t, bool> > >::iterator vei;
+
+ for (boost::tie(vi,vi_end) = vertices(g), vei = critical_edge_vectors.begin(); vi != vi_end; ++vi, ++vei)
+ {
+ vertex_descriptor_t u = *vi;
+ out_edge_iterator_t ei, ei_end;
+
+ gamma[u] = tau[u] = pi[u] = std::numeric_limits<edge_property_t>::max();
+ std::fill(vei->begin(), vei->end(), null_edge);
+
+ if (base_vertex(u) != u)
+ continue;
+
+ label_S[u] = label_T[u] = graph_traits<Graph>::null_vertex();
+ outlet[u] = u;
+
+ if (mate[u] == graph_traits<Graph>::null_vertex())
+ {
+ label_S[u] = u;
+ bloom(in_top_blossom(u));
+ }
+ }
+ }
+
+ bool augment_matching()
+ {
+ vertex_descriptor_t v, w, w_free_ancestor, v_free_ancestor;
+ v = w = w_free_ancestor = v_free_ancestor = graph_traits<Graph>::null_vertex();
+ bool found_alternating_path = false;
+
+ // note that we only use edges of zero slack value for augmenting
+ while (!even_edges.empty() && !found_alternating_path)
+ {
+ // search for augmenting paths depth-first
+ edge_descriptor_t current_edge = even_edges.back();
+ even_edges.pop_back();
+
+ v = source(current_edge, g);
+ w = target(current_edge, g);
+
+ vertex_descriptor_t v_prime = base_vertex(v);
+ vertex_descriptor_t w_prime = base_vertex(w);
+
+ // w_prime == v_prime implies that we get an edge that has been shrunk into a blossom
+ if (v_prime == w_prime)
+ continue;
+
+ // a paranoid check
+ if (label_S[v_prime] == graph_traits<Graph>::null_vertex())
+ {
+ std::swap(v_prime, w_prime);
+ std::swap(v, w);
+ }
+
+ // w_prime may be unlabeled or have a T-label; replace the existed T-label if the edge slack
+ // is smaller than current pi[w_prime] and update it. Note that a T-label is "deserved" only when pi equals zero.
+ // also update tau and tau_idx so that tau_idx becomes T-label when a T-blossom is expanded
+ if (label_S[w_prime] == graph_traits<Graph>::null_vertex())
+ {
+ if (slack(current_edge) < pi[w_prime])
+ put_T_label(w_prime, v, w, slack(current_edge));
+ if (slack(current_edge) < tau[w])
+ {
+ if (in_blossom[w]->father == blossom_ptr_t() || label_T[w_prime] == v ||
+ label_T[w_prime] == graph_traits<Graph>::null_vertex() ||
+ nearest_common_ancestor(v_prime, label_T[w_prime],
+ v_free_ancestor, w_free_ancestor) == graph_traits<Graph>::null_vertex())
+ {
+ tau[w] = slack(current_edge);
+ tau_idx[w] = v;
+ }
+ }
+ }
+
+ else
+ {
+ if (slack(current_edge) > 0)
+ {
+ // update gamma and critical_edges when we have a smaller edge slack
+ gamma[v_prime] = std::min(gamma[v_prime], slack(current_edge));
+ gamma[w_prime] = std::min(gamma[w_prime], slack(current_edge));
+ if (critical_edge[v_prime][w_prime] == null_edge ||
+ slack(critical_edge[v_prime][w_prime].first) > slack(current_edge))
+ {
+ critical_edge[v_prime][w_prime] = std::pair<edge_descriptor_t, bool>(current_edge, true);
+ critical_edge[w_prime][v_prime] = std::pair<edge_descriptor_t, bool>(current_edge, true);
+ }
+ continue;
+ }
+ else if (slack(current_edge) == 0)
+ {
+ // if nca is null_vertex then we have an augmenting path; otherwise we have
+ // a new top blossom with nca as its base vertex
+ vertex_descriptor_t nca = nearest_common_ancestor(v_prime, w_prime, v_free_ancestor, w_free_ancestor);
+
+ if (nca == graph_traits<Graph>::null_vertex())
+ found_alternating_path = true; //to break out of the loop
+ else
+ blossoming(v, v_prime, w, w_prime, nca);
+ }
+ }
+ }
+
+ if (!found_alternating_path)
+ return false;
+
+ augmenting(v, v_free_ancestor, w, w_free_ancestor);
+ return true;
+ }
+
+ // slack the vertex and blossom dual variables when there is no augmenting path found
+ // according to the primal-dual method
+ bool adjust_dual()
+ {
+ edge_property_t delta1, delta2, delta3, delta4, delta;
+ delta1 = delta2 = delta3 = delta4 = std::numeric_limits<edge_property_t>::max();
+
+ vertex_iterator_t vi, vi_end;
+
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ {
+ delta1 = std::min(delta1, dual_var[*vi]);
+ delta4 = pi[*vi] > 0 ? std::min(delta4, pi[*vi]) : delta4;
+ if (*vi == base_vertex(*vi))
+ delta3 = std::min(delta3, gamma[*vi]/2);
+ }
+
+ for (blossom_iterator_t bi = top_blossoms.begin(); bi != top_blossoms.end(); ++bi)
+ {
+ vertex_descriptor_t b_base = (*bi)->get_base();
+ if (label_T[b_base] != graph_traits<Graph>::null_vertex() && pi[b_base] == 0)
+ delta2 = std::min(delta2, (*bi)->dual_var/2);
+ }
+
+ delta = std::min(std::min(delta1, delta2), std::min(delta3, delta4));
+
+ // start updating dual variables, note that the order is important
+
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ {
+ vertex_descriptor_t v = *vi, v_prime = base_vertex(v);
+
+ if (label_S[v_prime] != graph_traits<Graph>::null_vertex())
+ dual_var[v] -= delta;
+ else if (label_T[v_prime] != graph_traits<Graph>::null_vertex() && pi[v_prime] == 0)
+ dual_var[v] += delta;
+
+ if (v == v_prime)
+ gamma[v] -= 2*delta;
+ }
+
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ {
+ vertex_descriptor_t v_prime = base_vertex(*vi);
+ if (pi[v_prime] > 0)
+ tau[*vi] -= delta;
+ }
+
+ for (blossom_iterator_t bi = top_blossoms.begin(); bi != top_blossoms.end(); ++bi)
+ {
+ vertex_descriptor_t b_base = (*bi)->get_base();
+ if (label_T[b_base] != graph_traits<Graph>::null_vertex() && pi[b_base] == 0)
+ (*bi)->dual_var -= 2*delta;
+ if (label_S[b_base] != graph_traits<Graph>::null_vertex())
+ (*bi)->dual_var += 2*delta;
+ }
+
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ {
+ vertex_descriptor_t v = *vi;
+ if (pi[v] > 0)
+ pi[v] -= delta;
+
+ // when some T-vertices have zero pi value, bloom their mates so that matching can be further augmented
+ if (label_T[v] != graph_traits<Graph>::null_vertex() && pi[v] == 0)
+ put_T_label(v, label_T[v], outlet[v], pi[v]);
+ }
+
+
+ // optimal solution reached, halt
+ if (delta == delta1)
+ return false;
+
+ // expand odd blossoms with zero dual variables and zero pi value of their base vertices
+ if (delta == delta2 && delta != delta3)
+ {
+ std::vector<blossom_ptr_t> new_top_blossoms;
+ for (blossom_iterator_t bi = top_blossoms.begin(); bi != top_blossoms.end();)
+ {
+ const blossom_ptr_t b = *bi;
+ vertex_descriptor_t b_base = b->get_base();
+ if (b->dual_var == 0 && label_T[b_base] != graph_traits<Graph>::null_vertex() && pi[b_base] == 0)
+ bi = expand_T_blossom(bi, new_top_blossoms);
+ else
+ ++bi;
+ }
+ top_blossoms.insert(top_blossoms.end(), new_top_blossoms.begin(), new_top_blossoms.end());
+ }
+
+ while (true)
+ {
+ // find a zero-slack critical edge (v, w) of zero gamma values
+ std::pair<edge_descriptor_t, bool> best_edge = null_edge;
+ std::vector<vertex_descriptor_t> base_nodes;
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ {
+ if (*vi == base_vertex(*vi))
+ base_nodes.push_back(*vi);
+ }
+ for (vertex_vec_iter_t i = base_nodes.begin(); i != base_nodes.end(); ++i)
+ {
+ if (gamma[*i] == 0)
+ {
+ for (vertex_vec_iter_t j = base_nodes.begin(); j != base_nodes.end(); ++j)
+ {
+ if (critical_edge[*i][*j] != null_edge && slack(critical_edge[*i][*j].first) == 0)
+ best_edge = critical_edge[*i][*j];
+ }
+ }
+ }
+
+ // if not found, continue finding other augment matching
+ if (best_edge == null_edge)
+ {
+ bool augmented = augment_matching();
+ return augmented || delta != delta1;
+ }
+ // if found, determine either augmenting or blossoming
+ vertex_descriptor_t v = source(best_edge.first, g), w = target(best_edge.first, g);
+ vertex_descriptor_t v_prime = base_vertex(v), w_prime = base_vertex(w), v_free_ancestor, w_free_ancestor;
+ vertex_descriptor_t nca = nearest_common_ancestor(v_prime, w_prime, v_free_ancestor, w_free_ancestor);
+ if (nca == graph_traits<Graph>::null_vertex())
+ {
+ augmenting(v, v_free_ancestor, w, w_free_ancestor);
+ return true;
+ }
+ else
+ blossoming(v, v_prime, w, w_prime, nca);
+ }
+
+ return false;
+ }
+
+ template <typename PropertyMap>
+ void get_current_matching(PropertyMap pm)
+ {
+ vertex_iterator_t vi, vi_end;
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ put(pm, *vi, mate[*vi]);
+ }
+
+ private:
+
+ const Graph& g;
+ VertexIndexMap vm;
+ const std::pair<edge_descriptor_t, bool> null_edge;
+
+ // storage for the property maps below
+ std::vector<vertex_descriptor_t> mate_vector;
+ std::vector<vertex_descriptor_t> label_S_vector, label_T_vector;
+ std::vector<vertex_descriptor_t> outlet_vector;
+ std::vector<vertex_descriptor_t> tau_idx_vector;
+ std::vector<edge_property_t> dual_var_vector;
+ std::vector<edge_property_t> pi_vector, gamma_vector, tau_vector;
+ std::vector<blossom_ptr_t> in_blossom_vector;
+ std::vector<std::pair<vertex_descriptor_t, vertex_descriptor_t> > old_label_vector;
+ std::vector<vertex_to_edge_map_t> critical_edge_vector;
+ std::vector<std::vector<std::pair<edge_descriptor_t, bool> > > critical_edge_vectors;
+
+ // iterator property maps
+ vertex_to_vertex_map_t mate;
+ vertex_to_vertex_map_t label_S; // v has an S-label -> v can be an even vertex, label_S[v] is its mate
+ vertex_to_vertex_map_t label_T; // v has a T-label -> v can be an odd vertex, label_T[v] is its predecessor in aug_path
+ vertex_to_vertex_map_t outlet;
+ vertex_to_vertex_map_t tau_idx;
+ vertex_to_weight_map_t dual_var;
+ vertex_to_weight_map_t pi, gamma, tau;
+ vertex_to_blossom_map_t in_blossom; // map any vertex v to the trivial blossom containing v
+ vertex_to_pair_map_t old_label; // <old T-label, old outlet> before relabeling or expanding T-blossoms
+ vertex_pair_to_edge_map_t critical_edge; // an not matched edge (v, w) is critical if v and w belongs to different S-blossoms
+
+ vertex_list_t aug_path;
+ edge_list_t even_edges;
+ std::vector<blossom_ptr_t> top_blossoms;
+
+ };
+
+ template <typename Graph, typename MateMap, typename VertexIndexMap>
+ void maximum_weighted_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
+ {
+ empty_matching<Graph, MateMap>::find_matching(g, mate);
+ weighted_augmenting_path_finder<Graph, MateMap, VertexIndexMap> augmentor(g, mate, vm);
+
+ // can have |V| times augmenting at most
+ for (std::size_t t = 0; t < num_vertices(g); ++t)
+ {
+ bool augmented = false;
+ while (!augmented)
+ {
+ augmented = augmentor.augment_matching();
+ if (!augmented)
+ {
+ // halt if adjusting dual variables can't bring potential augment
+ if (!augmentor.adjust_dual())
+ break;
+ }
+ }
+ if (!augmented)
+ break;
+ }
+
+ augmentor.get_current_matching(mate);
+ }
+
+ template <typename Graph, typename MateMap>
+ inline void maximum_weighted_matching(const Graph& g, MateMap mate)
+ {
+ maximum_weighted_matching(g, mate, get(vertex_index,g));
+ }
+
+ // brute-force matcher searches all possible combinations of matched edges to get the maximum weighted matching
+ // which can be used for testing on small graphs (within dozens vertices)
+ template <typename Graph, typename MateMap, typename VertexIndexMap>
+ class brute_force_matching
+ {
+ public:
+
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor_t;
+ typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
+ typedef typename std::vector<vertex_descriptor_t>::iterator vertex_vec_iter_t;
+ typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
+ typedef boost::iterator_property_map<vertex_vec_iter_t, VertexIndexMap> vertex_to_vertex_map_t;
+
+ brute_force_matching(const Graph& arg_g, MateMap arg_mate, VertexIndexMap arg_vm) :
+ g(arg_g),
+ vm(arg_vm),
+ mate_vector(num_vertices(g)),
+ best_mate_vector(num_vertices(g)),
+ mate(mate_vector.begin(), vm),
+ best_mate(best_mate_vector.begin(), vm)
+ {
+ vertex_iterator_t vi,vi_end;
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ best_mate[*vi] = mate[*vi] = get(arg_mate, *vi);
+ }
+
+ template <typename PropertyMap>
+ void find_matching(PropertyMap pm)
+ {
+ edge_iterator_t ei;
+ boost::tie(ei, ei_end) = edges(g);
+ select_edge(ei);
+
+ vertex_iterator_t vi,vi_end;
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ put(pm, *vi, best_mate[*vi]);
+ }
+
+ private:
+
+ const Graph& g;
+ VertexIndexMap vm;
+ std::vector<vertex_descriptor_t> mate_vector, best_mate_vector;
+ vertex_to_vertex_map_t mate, best_mate;
+ edge_iterator_t ei_end;
+
+ void select_edge(edge_iterator_t ei)
+ {
+ if (ei == ei_end)
+ {
+ if (matching_weight_sum(g, mate) > matching_weight_sum(g, best_mate))
+ {
+ vertex_iterator_t vi, vi_end;
+ for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
+ best_mate[*vi] = mate[*vi];
+ }
+ return;
+ }
+
+ vertex_descriptor_t v, w;
+ v = source(*ei, g);
+ w = target(*ei, g);
+
+ select_edge(++ei);
+
+ if (mate[v] == graph_traits<Graph>::null_vertex() &&
+ mate[w] == graph_traits<Graph>::null_vertex())
+ {
+ mate[v] = w;
+ mate[w] = v;
+ select_edge(ei);
+ mate[v] = mate[w] = graph_traits<Graph>::null_vertex();
+ }
+ }
+
+ };
+
+ template <typename Graph, typename MateMap, typename VertexIndexMap>
+ void brute_force_maximum_weighted_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
+ {
+ empty_matching<Graph, MateMap>::find_matching(g, mate);
+ brute_force_matching<Graph, MateMap, VertexIndexMap> brute_force_matcher(g, mate, vm);
+ brute_force_matcher.find_matching(mate);
+ }
+
+ template <typename Graph, typename MateMap>
+ inline void brute_force_maximum_weighted_matching(const Graph& g, MateMap mate)
+ {
+ brute_force_maximum_weighted_matching(g, mate, get(vertex_index, g));
+ }
+
+}
+
+#endif
diff --git a/boost/graph/metis.hpp b/boost/graph/metis.hpp
index 2ec2fc3e76..f6a1425f3e 100644
--- a/boost/graph/metis.hpp
+++ b/boost/graph/metis.hpp
@@ -26,8 +26,8 @@
namespace boost { namespace graph {
-class metis_exception : public std::exception {};
-class metis_input_exception : public metis_exception {};
+class BOOST_SYMBOL_VISIBLE metis_exception : public std::exception {};
+class BOOST_SYMBOL_VISIBLE metis_input_exception : public metis_exception {};
class metis_reader
{
diff --git a/boost/graph/minimum_degree_ordering.hpp b/boost/graph/minimum_degree_ordering.hpp
index 1e171da6cb..74ec912702 100644
--- a/boost/graph/minimum_degree_ordering.hpp
+++ b/boost/graph/minimum_degree_ordering.hpp
@@ -270,6 +270,7 @@ namespace boost {
typedef Marker<diff_t, vertex_t, VertexIndexMap> MarkerP;
// Data Members
+ bool has_no_edges;
// input parameters
Graph& G;
@@ -295,7 +296,7 @@ namespace boost {
PermutationMap perm,
SuperNodeMap supernode_size,
VertexIndexMap id)
- : G(g), delta(delta), degree(degree),
+ : has_no_edges(true), G(g), delta(delta), degree(degree),
inverse_perm(inverse_perm),
perm(perm),
supernode_size(supernode_size),
@@ -317,7 +318,9 @@ namespace boost {
// Initialize degreelists. Degreelists organizes the nodes
// according to their degree.
for (boost::tie(v, vend) = vertices(G); v != vend; ++v) {
- put(degree, *v, out_degree(*v, G));
+ typename Traits::degree_size_type d = out_degree(*v, G);
+ put(degree, *v, d);
+ if (0 < d) has_no_edges = false;
degreelists.push(*v);
}
}
@@ -336,6 +339,12 @@ namespace boost {
numbering.increment();
list_isolated.pop();
}
+
+ if (has_no_edges)
+ {
+ return;
+ }
+
size_type min_degree = 1;
typename DegreeLists::stack list_min_degree = degreelists[min_degree];
diff --git a/boost/graph/named_function_params.hpp b/boost/graph/named_function_params.hpp
index 4842dc9548..ec8dfb7c67 100644
--- a/boost/graph/named_function_params.hpp
+++ b/boost/graph/named_function_params.hpp
@@ -13,13 +13,16 @@
#include <functional>
#include <vector>
#include <boost/limits.hpp>
-#include <boost/ref.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/core/ref.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/preprocessor.hpp>
+#include <boost/parameter/is_argument_pack.hpp>
#include <boost/parameter/name.hpp>
#include <boost/parameter/binding.hpp>
#include <boost/type_traits.hpp>
-#include <boost/mpl/not.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/has_key.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/detail/d_ary_heap.hpp>
#include <boost/property_map/property_map.hpp>
@@ -394,9 +397,6 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
};
struct bgl_parameter_not_found_type {};
-
- template <typename ArgPack, typename KeywordType>
- struct parameter_exists : boost::mpl::not_<boost::is_same<typename boost::parameter::binding<ArgPack, KeywordType, bgl_parameter_not_found_type>::type, bgl_parameter_not_found_type> > {};
}
#define BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(old_type, old_var) \
@@ -419,12 +419,13 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
template <typename ArgPack, typename Tag, typename Prop, typename Graph>
struct override_const_property_result {
+ typedef typename boost::mpl::has_key<ArgPack, Tag>::type _parameter_exists;
typedef
typename override_const_property_t<
typename boost::parameter::value_type<ArgPack, Tag, int>::type,
Prop,
Graph,
- boost::detail::parameter_exists<ArgPack, Tag>::value
+ _parameter_exists::value
>::result_type
type;
};
@@ -432,18 +433,19 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
template <typename ArgPack, typename Tag, typename Prop, typename Graph>
typename override_const_property_result<ArgPack, Tag, Prop, Graph>::type
override_const_property(const ArgPack& ap, const boost::parameter::keyword<Tag>& t, const Graph& g, Prop) {
+ typedef typename boost::mpl::has_key<ArgPack, Tag>::type _parameter_exists;
return override_const_property_t<
typename boost::parameter::value_type<ArgPack, Tag, int>::type,
Prop,
Graph,
- boost::detail::parameter_exists<ArgPack, Tag>::value
+ _parameter_exists::value
>()(g, ap[t | 0]);
}
template <typename ArgType, typename Prop, typename Graph, bool Exists>
struct override_property_t {
typedef ArgType result_type;
- result_type operator()(const Graph&, const typename boost::add_reference<ArgType>::type a) const {return a;}
+ result_type operator()(const Graph&, typename boost::add_lvalue_reference<ArgType>::type a) const {return a;}
};
template <typename ArgType, typename Prop, typename Graph>
@@ -454,12 +456,13 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
template <typename ArgPack, typename Tag, typename Prop, typename Graph>
struct override_property_result {
+ typedef typename boost::mpl::has_key<ArgPack, Tag>::type _parameter_exists;
typedef
typename override_property_t<
typename boost::parameter::value_type<ArgPack, Tag, int>::type,
Prop,
Graph,
- boost::detail::parameter_exists<ArgPack, Tag>::value
+ _parameter_exists::value
>::result_type
type;
};
@@ -467,11 +470,12 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
template <typename ArgPack, typename Tag, typename Prop, typename Graph>
typename override_property_result<ArgPack, Tag, Prop, Graph>::type
override_property(const ArgPack& ap, const boost::parameter::keyword<Tag>& t, const Graph& g, Prop) {
+ typedef typename boost::mpl::has_key<ArgPack, Tag>::type _parameter_exists;
return override_property_t<
typename boost::parameter::value_type<ArgPack, Tag, int>::type,
Prop,
Graph,
- boost::detail::parameter_exists<ArgPack, Tag>::value
+ _parameter_exists::value
>()(g, ap[t | 0]);
}
@@ -482,7 +486,7 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
typedef boost::parameter::aux::tagged_argument<K, A> type;
};
-#define BOOST_GRAPH_OPENING_PART_OF_PAIR(z, i, n) boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<BOOST_PP_CAT(Keyword, BOOST_PP_SUB(n, i)), BOOST_PP_CAT(Arg, BOOST_PP_SUB(n, i))>,
+#define BOOST_GRAPH_OPENING_PART_OF_PAIR(z, i, n) boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<BOOST_PP_CAT(Keyword, BOOST_PP_SUB(n, i)), BOOST_PP_CAT(Arg, BOOST_PP_SUB(n, i))>,
#define BOOST_GRAPH_MAKE_PAIR_PARAM(z, i, _) const boost::parameter::aux::tagged_argument<BOOST_PP_CAT(Keyword, i), BOOST_PP_CAT(Arg, i)>& BOOST_PP_CAT(kw, i)
#define BOOST_GRAPH_MAKE_AP_TYPE_SPECIALIZATION(z, i, _) \
@@ -511,17 +515,26 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONEX(z, nnamed, BOOST_PP_SEQ_ELEM(0, seq), BOOST_PP_SEQ_ELEM(1, seq))
#define BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONEX(z, nnamed, name, nfixed) \
- template <BOOST_PP_ENUM_PARAMS(nfixed, typename Param) BOOST_PP_ENUM_TRAILING_PARAMS(nnamed, typename Keyword) BOOST_PP_ENUM_TRAILING_PARAMS(nnamed, typename Arg)> \
- typename boost::result_of< \
- detail::BOOST_PP_CAT(name, _impl)<BOOST_PP_ENUM_PARAMS(nfixed, Param)> \
- (BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_COMMA_IF(nfixed) \
- const typename boost::detail::make_arg_pack_type<void(BOOST_PP_ENUM_PARAMS(nnamed, Keyword) BOOST_PP_COMMA_IF(nnamed) BOOST_PP_ENUM_PARAMS(nnamed, Arg))>::type&) \
- >::type \
- name(BOOST_PP_ENUM_BINARY_PARAMS(nfixed, const Param, & param) \
- BOOST_PP_ENUM_TRAILING(nnamed, BOOST_GRAPH_MAKE_PAIR_PARAM, ~)) { \
- return detail::BOOST_PP_CAT(name, _impl)<BOOST_PP_ENUM_PARAMS(nfixed, Param)>() \
- (BOOST_PP_ENUM_PARAMS(nfixed, param), \
- (boost::parameter::aux::empty_arg_list() BOOST_PP_ENUM_TRAILING_PARAMS(nnamed, kw))); \
+ template < \
+ BOOST_PP_ENUM_PARAMS_Z(z, nfixed, typename Param) \
+ BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, nnamed, typename ArgumentPack) \
+ > \
+ typename \
+ BOOST_PP_EXPR_IF(nnamed, boost::lazy_enable_if<boost::parameter::is_argument_pack<ArgumentPack0>) \
+ BOOST_PP_COMMA_IF(nnamed) \
+ ::boost::graph::detail::BOOST_PP_CAT(name, _impl)<BOOST_PP_ENUM_PARAMS_Z(z, nfixed, Param)> \
+ BOOST_PP_EXPR_IF(nnamed, >)::type \
+ name( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, nfixed, Param, const& param) \
+ BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, nnamed, ArgumentPack, const& tagged_arg) \
+ ) \
+ { \
+ return ::boost::graph::BOOST_PP_CAT(name, _with_named_params)( \
+ BOOST_PP_ENUM_PARAMS_Z(z, nfixed, param) \
+ BOOST_PP_COMMA_IF(nnamed) BOOST_PP_LPAREN_IF(nnamed) \
+ BOOST_PP_ENUM_PARAMS_Z(z, nnamed, tagged_arg) \
+ BOOST_PP_RPAREN_IF(nnamed) \
+ ); \
}
#define BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(name, nfixed) \
@@ -536,7 +549,6 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(old_style_params_type, old_style_params) \
return ::boost::graph::BOOST_PP_CAT(name, _with_named_params)(BOOST_PP_ENUM_PARAMS(nfixed, param) BOOST_PP_COMMA_IF(nfixed) arg_pack); \
} \
- \
BOOST_PP_EXPR_IF(nfixed, template <) BOOST_PP_ENUM_PARAMS(nfixed, typename Param) BOOST_PP_EXPR_IF(nfixed, >) \
BOOST_PP_EXPR_IF(nfixed, typename) boost::result_of< \
::boost::graph::detail::BOOST_PP_CAT(name, _impl) BOOST_PP_EXPR_IF(nfixed, <) BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_EXPR_IF(nfixed, >) \
@@ -561,14 +573,17 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
template <typename Graph, typename ArgPack, typename Value, typename PM>
struct map_maker_helper<false, Graph, ArgPack, Value, PM> {
+ typedef typename boost::mpl::has_key<
+ ArgPack
+ , boost::graph::keywords::tag::vertex_index_map
+ >::type _parameter_exists;
typedef typename boost::remove_const<
typename override_const_property_t<
typename boost::parameter::value_type<
ArgPack, boost::graph::keywords::tag::vertex_index_map, int>::type,
boost::vertex_index_t,
Graph,
- boost::detail::parameter_exists<
- ArgPack, boost::graph::keywords::tag::vertex_index_map>::value
+ _parameter_exists::value
>::result_type>::type vi_map_type;
typedef
boost::shared_array_property_map<Value, vi_map_type>
@@ -589,11 +604,8 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
template <typename Graph, typename ArgPack, typename MapTag, typename ValueType>
struct map_maker {
- BOOST_STATIC_CONSTANT(
- bool,
- has_map =
- (parameter_exists<ArgPack, MapTag>
- ::value));
+ typedef typename boost::mpl::has_key<ArgPack, MapTag>::type _parameter_exists;
+ BOOST_STATIC_CONSTANT(bool, has_map = (_parameter_exists::value));
typedef map_maker_helper<has_map, Graph, ArgPack, ValueType,
typename boost::remove_const<
typename boost::parameter::value_type<
@@ -666,11 +678,8 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
template <class Graph, class ArgPack, class KeyT, class ValueT, class PriorityQueueTag, class KeyMapTag, class IndexInHeapMapTag, class Compare>
struct priority_queue_maker {
- BOOST_STATIC_CONSTANT(
- bool,
- g_hasQ =
- (parameter_exists<ArgPack, PriorityQueueTag>
- ::value));
+ typedef typename boost::mpl::has_key<ArgPack, PriorityQueueTag>::type _parameter_exists;
+ BOOST_STATIC_CONSTANT(bool, g_hasQ = (_parameter_exists::value));
typedef boost::reference_wrapper<int> int_refw;
typedef typename boost::parameter::value_type<
ArgPack,
diff --git a/boost/graph/one_bit_color_map.hpp b/boost/graph/one_bit_color_map.hpp
index b153b732f7..aaf8943b00 100644
--- a/boost/graph/one_bit_color_map.hpp
+++ b/boost/graph/one_bit_color_map.hpp
@@ -16,6 +16,7 @@
#include <boost/property_map/property_map.hpp>
#include <boost/graph/properties.hpp>
+#include <boost/graph/detail/mpi_include.hpp>
#include <boost/shared_array.hpp>
#include <boost/config.hpp>
#include <boost/assert.hpp>
@@ -97,8 +98,6 @@ make_one_bit_color_map(std::size_t n, const IndexMap& index_map)
} // end namespace boost
-#endif // BOOST_ONE_BIT_COLOR_MAP_HPP
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/one_bit_color_map.hpp>)
-#ifdef BOOST_GRAPH_USE_MPI
-# include <boost/graph/distributed/one_bit_color_map.hpp>
-#endif
+#endif // BOOST_ONE_BIT_COLOR_MAP_HPP
diff --git a/boost/graph/page_rank.hpp b/boost/graph/page_rank.hpp
index a8987046d3..1285444936 100644
--- a/boost/graph/page_rank.hpp
+++ b/boost/graph/page_rank.hpp
@@ -16,6 +16,7 @@
#include <boost/graph/properties.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/overloading.hpp>
+#include <boost/graph/detail/mpi_include.hpp>
#include <vector>
namespace boost { namespace graph {
@@ -154,8 +155,6 @@ remove_dangling_links(MutableGraph& g
} } // end namespace boost::graph
-#ifdef BOOST_GRAPH_USE_MPI
-# include <boost/graph/distributed/page_rank.hpp>
-#endif
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/page_rank.hpp>)
#endif // BOOST_GRAPH_PAGE_RANK_HPP
diff --git a/boost/graph/parallel/distribution.hpp b/boost/graph/parallel/distribution.hpp
index 8256b197e7..6dc974c1ae 100644
--- a/boost/graph/parallel/distribution.hpp
+++ b/boost/graph/parallel/distribution.hpp
@@ -22,6 +22,7 @@
#include <boost/iterator/counting_iterator.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/config.hpp>
#include <typeinfo>
namespace boost { namespace parallel {
@@ -461,8 +462,12 @@ class twod_random
make_counting_iterator(global_to_local.size()),
global_to_local.begin());
+#if defined(BOOST_NO_CXX98_RANDOM_SHUFFLE)
+ std::shuffle(global_to_local.begin(), global_to_local.end(), gen);
+#else
random_int<RandomNumberGen> rand(gen);
std::random_shuffle(global_to_local.begin(), global_to_local.end(), rand);
+#endif
}
template<typename SizeType>
@@ -563,9 +568,12 @@ class random_distribution
make_counting_iterator(n),
local_to_global.begin());
+#if defined(BOOST_NO_CXX98_RANDOM_SHUFFLE)
+ std::shuffle(local_to_global.begin(), local_to_global.end(), gen);
+#else
random_int<RandomNumberGen> rand(gen);
std::random_shuffle(local_to_global.begin(), local_to_global.end(), rand);
-
+#endif
for (std::vector<std::size_t>::size_type i = 0; i < n; ++i)
global_to_local[local_to_global[i]] = i;
diff --git a/boost/graph/planar_detail/boyer_myrvold_impl.hpp b/boost/graph/planar_detail/boyer_myrvold_impl.hpp
index 45a552aa5d..f1b3cec822 100644
--- a/boost/graph/planar_detail/boyer_myrvold_impl.hpp
+++ b/boost/graph/planar_detail/boyer_myrvold_impl.hpp
@@ -591,7 +591,8 @@ namespace boost
first_face_itr, second_face_itr, face_end;
vertex_t first_side_vertex
= graph_traits<Graph>::null_vertex();
- vertex_t second_side_vertex;
+ vertex_t second_side_vertex
+ = graph_traits<Graph>::null_vertex();
vertex_t first_tail, second_tail;
first_tail = second_tail = curr_face_handle.get_anchor();
diff --git a/boost/graph/profile.hpp b/boost/graph/profile.hpp
index 1ff99de5c4..54163c5af2 100644
--- a/boost/graph/profile.hpp
+++ b/boost/graph/profile.hpp
@@ -1,7 +1,8 @@
//
//=======================================================================
// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch)
-// ETH Zurich, Center of Structure Technologies (www.imes.ethz.ch/st)
+// ETH Zurich, Center of Structure Technologies
+// (https://web.archive.org/web/20050307090307/http://www.structures.ethz.ch/)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
diff --git a/boost/graph/r_c_shortest_paths.hpp b/boost/graph/r_c_shortest_paths.hpp
index 7e490fc7d2..ccd778c92e 100644
--- a/boost/graph/r_c_shortest_paths.hpp
+++ b/boost/graph/r_c_shortest_paths.hpp
@@ -2,7 +2,7 @@
// Copyright Michael Drexl 2005, 2006.
// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP
@@ -13,6 +13,8 @@
#include <vector>
#include <list>
+#include <boost/make_shared.hpp>
+#include <boost/enable_shared_from_this.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/property_map/property_map.hpp>
@@ -21,25 +23,23 @@ namespace boost {
// r_c_shortest_paths_label struct
template<class Graph, class Resource_Container>
-struct r_c_shortest_paths_label
+struct r_c_shortest_paths_label : public boost::enable_shared_from_this<r_c_shortest_paths_label<Graph, Resource_Container> >
{
r_c_shortest_paths_label
- ( const unsigned long n,
- const Resource_Container& rc = Resource_Container(),
- const r_c_shortest_paths_label* const pl = 0,
- const typename graph_traits<Graph>::edge_descriptor& ed =
- graph_traits<Graph>::edge_descriptor(),
- const typename graph_traits<Graph>::vertex_descriptor& vd =
- graph_traits<Graph>::vertex_descriptor() )
- : num( n ),
- cumulated_resource_consumption( rc ),
- p_pred_label( pl ),
- pred_edge( ed ),
- resident_vertex( vd ),
- b_is_dominated( false ),
- b_is_processed( false ),
- b_is_valid( true )
+ ( const unsigned long n,
+ const Resource_Container& rc = Resource_Container(),
+ const boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > pl = boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> >(),
+ const typename graph_traits<Graph>::edge_descriptor& ed = graph_traits<Graph>::edge_descriptor(),
+ const typename graph_traits<Graph>::vertex_descriptor& vd = graph_traits<Graph>::vertex_descriptor() )
+ : num( n ),
+ cumulated_resource_consumption( rc ),
+ p_pred_label( pl ),
+ pred_edge( ed ),
+ resident_vertex( vd ),
+ b_is_dominated( false ),
+ b_is_processed( false )
{}
+
r_c_shortest_paths_label& operator=( const r_c_shortest_paths_label& other )
{
if( this == &other )
@@ -50,179 +50,162 @@ struct r_c_shortest_paths_label
}
const unsigned long num;
Resource_Container cumulated_resource_consumption;
- const r_c_shortest_paths_label* const p_pred_label;
+ const boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > p_pred_label;
const typename graph_traits<Graph>::edge_descriptor pred_edge;
const typename graph_traits<Graph>::vertex_descriptor resident_vertex;
bool b_is_dominated;
bool b_is_processed;
- bool b_is_valid;
}; // r_c_shortest_paths_label
template<class Graph, class Resource_Container>
inline bool operator==
-( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
+( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
{
- assert (l1.b_is_valid && l2.b_is_valid);
- return
+ return
l1.cumulated_resource_consumption == l2.cumulated_resource_consumption;
}
template<class Graph, class Resource_Container>
inline bool operator!=
-( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
+( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
{
- assert (l1.b_is_valid && l2.b_is_valid);
- return
+ return
!( l1 == l2 );
}
template<class Graph, class Resource_Container>
inline bool operator<
-( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
+( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
{
- assert (l1.b_is_valid && l2.b_is_valid);
- return
+ return
l1.cumulated_resource_consumption < l2.cumulated_resource_consumption;
}
template<class Graph, class Resource_Container>
inline bool operator>
-( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
+( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
{
- assert (l1.b_is_valid && l2.b_is_valid);
- return
+ return
l2.cumulated_resource_consumption < l1.cumulated_resource_consumption;
}
template<class Graph, class Resource_Container>
inline bool operator<=
-( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
+( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
{
- assert (l1.b_is_valid && l2.b_is_valid);
- return
+ return
l1 < l2 || l1 == l2;
}
template<class Graph, class Resource_Container>
inline bool operator>=
-( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
+( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
{
- assert (l1.b_is_valid && l2.b_is_valid);
return l2 < l1 || l1 == l2;
}
-namespace detail {
+template<typename Graph, typename Resource_Container>
+inline bool operator<
+ ( const boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > &t,
+ const boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > &u) {
+ return *t < *u;
+}
-// ks_smart_pointer class
-// from:
-// Kuhlins, S.; Schader, M. (1999):
-// Die C++-Standardbibliothek
-// Springer, Berlin
-// p. 333 f.
-template<class T>
-class ks_smart_pointer
-{
-public:
- ks_smart_pointer( T* ptt = 0 ) : pt( ptt ) {}
- ks_smart_pointer( const ks_smart_pointer& other ) : pt( other.pt ) {}
- ks_smart_pointer& operator=( const ks_smart_pointer& other )
- { pt = other.pt; return *this; }
- ~ks_smart_pointer() {}
- T& operator*() const { return *pt; }
- T* operator->() const { return pt; }
- T* get() const { return pt; }
- operator T*() const { return pt; }
- friend bool operator==( const ks_smart_pointer& t,
- const ks_smart_pointer& u )
- { return *t.pt == *u.pt; }
- friend bool operator!=( const ks_smart_pointer& t,
- const ks_smart_pointer& u )
- { return *t.pt != *u.pt; }
- friend bool operator<( const ks_smart_pointer& t,
- const ks_smart_pointer& u )
- { return *t.pt < *u.pt; }
- friend bool operator>( const ks_smart_pointer& t,
- const ks_smart_pointer& u )
- { return *t.pt > *u.pt; }
- friend bool operator<=( const ks_smart_pointer& t,
- const ks_smart_pointer& u )
- { return *t.pt <= *u.pt; }
- friend bool operator>=( const ks_smart_pointer& t,
- const ks_smart_pointer& u )
- { return *t.pt >= *u.pt; }
-private:
- T* pt;
-}; // ks_smart_pointer
+template<typename Graph, typename Resource_Container>
+inline bool operator<=( const boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > &t,
+ const boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > &u ) {
+ return *t <= *u;
+}
+
+template<typename Graph, typename Resource_Container>
+inline bool operator>
+ (
+ const boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > &t,
+ const boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > &u ) {
+ return *t > *u;
+}
+template<typename Graph, typename Resource_Container>
+inline bool operator>=
+ (
+ const boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > &t,
+ const boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > &u) {
+ return *t >= *u;
+}
+
+namespace detail {
// r_c_shortest_paths_dispatch function (body/implementation)
-template<class Graph,
- class VertexIndexMap,
- class EdgeIndexMap,
- class Resource_Container,
- class Resource_Extension_Function,
- class Dominance_Function,
- class Label_Allocator,
+template<class Graph,
+ class VertexIndexMap,
+ class EdgeIndexMap,
+ class Resource_Container,
+ class Resource_Extension_Function,
+ class Dominance_Function,
+ class Label_Allocator,
class Visitor>
void r_c_shortest_paths_dispatch
-( const Graph& g,
- const VertexIndexMap& vertex_index_map,
- const EdgeIndexMap& /*edge_index_map*/,
- typename graph_traits<Graph>::vertex_descriptor s,
- typename graph_traits<Graph>::vertex_descriptor t,
+( const Graph& g,
+ const VertexIndexMap& vertex_index_map,
+ const EdgeIndexMap& /*edge_index_map*/,
+ typename graph_traits<Graph>::vertex_descriptor s,
+ typename graph_traits<Graph>::vertex_descriptor t,
// each inner vector corresponds to a pareto-optimal path
std::vector
<std::vector
<typename graph_traits
- <Graph>::edge_descriptor> >& pareto_optimal_solutions,
+ <Graph>::edge_descriptor> >& pareto_optimal_solutions,
std::vector
- <Resource_Container>& pareto_optimal_resource_containers,
- bool b_all_pareto_optimal_solutions,
- // to initialize the first label/resource container
+ <Resource_Container>& pareto_optimal_resource_containers,
+ bool b_all_pareto_optimal_solutions,
+ // to initialize the first label/resource container
// and to carry the type information
- const Resource_Container& rc,
- Resource_Extension_Function& ref,
- Dominance_Function& dominance,
+ const Resource_Container& rc,
+ Resource_Extension_Function& ref,
+ Dominance_Function& dominance,
// to specify the memory management strategy for the labels
- Label_Allocator /*la*/,
+ Label_Allocator /*la*/,
Visitor vis )
{
pareto_optimal_resource_containers.clear();
pareto_optimal_solutions.clear();
size_t i_label_num = 0;
- typedef
- typename
+#if defined(BOOST_NO_CXX11_ALLOCATOR)
+ typedef
+ typename
Label_Allocator::template rebind
<r_c_shortest_paths_label
<Graph, Resource_Container> >::other LAlloc;
+#else
+ typedef
+ typename
+ std::allocator_traits<Label_Allocator>::template rebind_alloc
+ <r_c_shortest_paths_label
+ <Graph, Resource_Container> > LAlloc;
+ typedef std::allocator_traits<LAlloc> LTraits;
+#endif
LAlloc l_alloc;
- typedef
- ks_smart_pointer
- <r_c_shortest_paths_label<Graph, Resource_Container> > Splabel;
- std::priority_queue<Splabel, std::vector<Splabel>, std::greater<Splabel> >
+ typedef
+ boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > Splabel;
+ std::priority_queue<Splabel, std::vector<Splabel>, std::greater<Splabel> >
unprocessed_labels;
bool b_feasible = true;
- r_c_shortest_paths_label<Graph, Resource_Container>* first_label =
- l_alloc.allocate( 1 );
- l_alloc.construct
- ( first_label,
- r_c_shortest_paths_label
- <Graph, Resource_Container>( i_label_num++,
- rc,
- 0,
- typename graph_traits<Graph>::
- edge_descriptor(),
- s ) );
-
- Splabel splabel_first_label = Splabel( first_label );
+ Splabel splabel_first_label = boost::allocate_shared<r_c_shortest_paths_label<Graph, Resource_Container> >(
+ l_alloc,
+ i_label_num++,
+ rc,
+ boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> >(),
+ typename graph_traits<Graph>::edge_descriptor(),
+ s );
+
unprocessed_labels.push( splabel_first_label );
std::vector<std::list<Splabel> > vec_vertex_labels_data( num_vertices( g ) );
iterator_property_map<typename std::vector<std::list<Splabel> >::iterator,
@@ -230,7 +213,7 @@ void r_c_shortest_paths_dispatch
vec_vertex_labels(vec_vertex_labels_data.begin(), vertex_index_map);
vec_vertex_labels[s].push_back( splabel_first_label );
typedef
- std::vector<typename std::list<Splabel>::iterator>
+ std::vector<typename std::list<Splabel>::iterator>
vec_last_valid_positions_for_dominance_data_type;
vec_last_valid_positions_for_dominance_data_type
vec_last_valid_positions_for_dominance_data( num_vertices( g ) );
@@ -247,7 +230,7 @@ void r_c_shortest_paths_dispatch
iterator_property_map<std::vector<size_t>::iterator, VertexIndexMap>
vec_last_valid_index_for_dominance
(vec_last_valid_index_for_dominance_data.begin(), vertex_index_map);
- std::vector<bool>
+ std::vector<bool>
b_vec_vertex_already_checked_for_dominance_data( num_vertices( g ), false );
iterator_property_map<std::vector<bool>::iterator, VertexIndexMap>
b_vec_vertex_already_checked_for_dominance
@@ -257,42 +240,39 @@ void r_c_shortest_paths_dispatch
while( !unprocessed_labels.empty() && vis.on_enter_loop(unprocessed_labels, g) )
{
Splabel cur_label = unprocessed_labels.top();
- assert (cur_label->b_is_valid);
unprocessed_labels.pop();
vis.on_label_popped( *cur_label, g );
- // an Splabel object in unprocessed_labels and the respective Splabel
- // object in the respective list<Splabel> of vec_vertex_labels share their
+ // an Splabel object in unprocessed_labels and the respective Splabel
+ // object in the respective list<Splabel> of vec_vertex_labels share their
// embedded r_c_shortest_paths_label object
- // to avoid memory leaks, dominated
- // r_c_shortest_paths_label objects are marked and deleted when popped
- // from unprocessed_labels, as they can no longer be deleted at the end of
- // the function; only the Splabel object in unprocessed_labels still
+ // to avoid memory leaks, dominated
+ // r_c_shortest_paths_label objects are marked and deleted when popped
+ // from unprocessed_labels, as they can no longer be deleted at the end of
+ // the function; only the Splabel object in unprocessed_labels still
// references the r_c_shortest_paths_label object
- // this is also for efficiency, because the else branch is executed only
- // if there is a chance that extending the
- // label leads to new undominated labels, which in turn is possible only
+ // this is also for efficiency, because the else branch is executed only
+ // if there is a chance that extending the
+ // label leads to new undominated labels, which in turn is possible only
// if the label to be extended is undominated
- assert (cur_label->b_is_valid);
if( !cur_label->b_is_dominated )
{
typename boost::graph_traits<Graph>::vertex_descriptor
i_cur_resident_vertex = cur_label->resident_vertex;
- std::list<Splabel>& list_labels_cur_vertex =
+ std::list<Splabel>& list_labels_cur_vertex =
get(vec_vertex_labels, i_cur_resident_vertex);
- if( list_labels_cur_vertex.size() >= 2
- && vec_last_valid_index_for_dominance[i_cur_resident_vertex]
+ if( list_labels_cur_vertex.size() >= 2
+ && vec_last_valid_index_for_dominance[i_cur_resident_vertex]
< list_labels_cur_vertex.size() )
{
- typename std::list<Splabel>::iterator outer_iter =
+ typename std::list<Splabel>::iterator outer_iter =
list_labels_cur_vertex.begin();
bool b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = false;
while( outer_iter != list_labels_cur_vertex.end() )
{
Splabel cur_outer_splabel = *outer_iter;
- assert (cur_outer_splabel->b_is_valid);
typename std::list<Splabel>::iterator inner_iter = outer_iter;
- if( !b_outer_iter_at_or_beyond_last_valid_pos_for_dominance
- && outer_iter ==
+ if( !b_outer_iter_at_or_beyond_last_valid_pos_for_dominance
+ && outer_iter ==
get(vec_last_valid_positions_for_dominance,
i_cur_resident_vertex) )
b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = true;
@@ -303,7 +283,7 @@ void r_c_shortest_paths_dispatch
}
else
{
- inner_iter =
+ inner_iter =
get(vec_last_valid_positions_for_dominance,
i_cur_resident_vertex);
++inner_iter;
@@ -312,9 +292,8 @@ void r_c_shortest_paths_dispatch
while( inner_iter != list_labels_cur_vertex.end() )
{
Splabel cur_inner_splabel = *inner_iter;
- assert (cur_inner_splabel->b_is_valid);
if( dominance( cur_outer_splabel->
- cumulated_resource_consumption,
+ cumulated_resource_consumption,
cur_inner_splabel->
cumulated_resource_consumption ) )
{
@@ -323,9 +302,7 @@ void r_c_shortest_paths_dispatch
list_labels_cur_vertex.erase( buf );
if( cur_inner_splabel->b_is_processed )
{
- cur_inner_splabel->b_is_valid = false;
- l_alloc.destroy( cur_inner_splabel.get() );
- l_alloc.deallocate( cur_inner_splabel.get(), 1 );
+ cur_inner_splabel.reset();
}
else
cur_inner_splabel->b_is_dominated = true;
@@ -334,7 +311,7 @@ void r_c_shortest_paths_dispatch
else
++inner_iter;
if( dominance( cur_inner_splabel->
- cumulated_resource_consumption,
+ cumulated_resource_consumption,
cur_outer_splabel->
cumulated_resource_consumption ) )
{
@@ -342,12 +319,9 @@ void r_c_shortest_paths_dispatch
++outer_iter;
list_labels_cur_vertex.erase( buf );
b_outer_iter_erased = true;
- assert (cur_outer_splabel->b_is_valid);
if( cur_outer_splabel->b_is_processed )
{
- cur_outer_splabel->b_is_valid = false;
- l_alloc.destroy( cur_outer_splabel.get() );
- l_alloc.deallocate( cur_outer_splabel.get(), 1 );
+ cur_outer_splabel.reset();
}
else
cur_outer_splabel->b_is_dominated = true;
@@ -369,28 +343,22 @@ void r_c_shortest_paths_dispatch
list_labels_cur_vertex.size() - 1);
}
}
- assert (b_all_pareto_optimal_solutions || cur_label->b_is_valid);
if( !b_all_pareto_optimal_solutions && cur_label->resident_vertex == t )
{
// the devil don't sleep
if( cur_label->b_is_dominated )
{
- cur_label->b_is_valid = false;
- l_alloc.destroy( cur_label.get() );
- l_alloc.deallocate( cur_label.get(), 1 );
+ cur_label.reset();
}
while( unprocessed_labels.size() )
{
Splabel l = unprocessed_labels.top();
- assert (l->b_is_valid);
unprocessed_labels.pop();
- // delete only dominated labels, because nondominated labels are
+ // delete only dominated labels, because nondominated labels are
// deleted at the end of the function
if( l->b_is_dominated )
{
- l->b_is_valid = false;
- l_alloc.destroy( l.get() );
- l_alloc.deallocate( l.get(), 1 );
+ l.reset();
}
}
break;
@@ -399,56 +367,45 @@ void r_c_shortest_paths_dispatch
{
cur_label->b_is_processed = true;
vis.on_label_not_dominated( *cur_label, g );
- typename graph_traits<Graph>::vertex_descriptor cur_vertex =
+ typename graph_traits<Graph>::vertex_descriptor cur_vertex =
cur_label->resident_vertex;
typename graph_traits<Graph>::out_edge_iterator oei, oei_end;
- for( boost::tie( oei, oei_end ) = out_edges( cur_vertex, g );
- oei != oei_end;
+ for( boost::tie( oei, oei_end ) = out_edges( cur_vertex, g );
+ oei != oei_end;
++oei )
{
b_feasible = true;
- r_c_shortest_paths_label<Graph, Resource_Container>* new_label =
- l_alloc.allocate( 1 );
- l_alloc.construct( new_label,
- r_c_shortest_paths_label
- <Graph, Resource_Container>
- ( i_label_num++,
- cur_label->cumulated_resource_consumption,
- cur_label.get(),
- *oei,
- target( *oei, g ) ) );
- b_feasible =
- ref( g,
- new_label->cumulated_resource_consumption,
- new_label->p_pred_label->cumulated_resource_consumption,
+ Splabel new_label = boost::allocate_shared<r_c_shortest_paths_label<Graph, Resource_Container> >(
+ l_alloc,
+ i_label_num++,
+ cur_label->cumulated_resource_consumption,
+ cur_label,
+ *oei,
+ target( *oei, g ) );
+ b_feasible =
+ ref( g,
+ new_label->cumulated_resource_consumption,
+ new_label->p_pred_label->cumulated_resource_consumption,
new_label->pred_edge );
if( !b_feasible )
{
vis.on_label_not_feasible( *new_label, g );
- new_label->b_is_valid = false;
- l_alloc.destroy( new_label );
- l_alloc.deallocate( new_label, 1 );
+ new_label.reset();
}
else
{
- const r_c_shortest_paths_label<Graph, Resource_Container>&
- ref_new_label = *new_label;
- vis.on_label_feasible( ref_new_label, g );
- Splabel new_sp_label( new_label );
- vec_vertex_labels[new_sp_label->resident_vertex].
- push_back( new_sp_label );
- unprocessed_labels.push( new_sp_label );
+ vis.on_label_feasible( *new_label, g );
+ vec_vertex_labels[new_label->resident_vertex].
+ push_back( new_label );
+ unprocessed_labels.push( new_label );
}
}
}
else
{
- assert (cur_label->b_is_valid);
vis.on_label_dominated( *cur_label, g );
- cur_label->b_is_valid = false;
- l_alloc.destroy( cur_label.get() );
- l_alloc.deallocate( cur_label.get(), 1 );
+ cur_label.reset();
}
}
std::list<Splabel> dsplabels = get(vec_vertex_labels, t);
@@ -459,18 +416,31 @@ void r_c_shortest_paths_dispatch
{
for( ; csi != csi_end; ++csi )
{
- std::vector<typename graph_traits<Graph>::edge_descriptor>
+ std::vector<typename graph_traits<Graph>::edge_descriptor>
cur_pareto_optimal_path;
- const r_c_shortest_paths_label<Graph, Resource_Container>* p_cur_label =
- (*csi).get();
- assert (p_cur_label->b_is_valid);
+ boost::shared_ptr<r_c_shortest_paths_label<Graph, Resource_Container> > p_cur_label = *csi;
pareto_optimal_resource_containers.
push_back( p_cur_label->cumulated_resource_consumption );
while( p_cur_label->num != 0 )
{
cur_pareto_optimal_path.push_back( p_cur_label->pred_edge );
p_cur_label = p_cur_label->p_pred_label;
- assert (p_cur_label->b_is_valid);
+
+ // assertion b_is_valid beyond this point is not correct if the domination function
+ // requires resource levels to be strictly greater than existing values
+ //
+ // Example
+ // Customers
+ // id min_arrival max_departure
+ // 2 0 974
+ // 3 0 972
+ // 4 0 964
+ // 5 678 801
+ //
+ // Path A: 2-3-4-5 (times: 0-16-49-84-678)
+ // Path B: 3-2-4-5 (times: 0-18-51-62-678)
+ // The partial path 3-2-4 dominates the other partial path 2-3-4,
+ // though the path 3-2-4-5 does not strictly dominate the path 2-3-4-5
}
pareto_optimal_solutions.push_back( cur_pareto_optimal_path );
if( !b_all_pareto_optimal_solutions )
@@ -479,14 +449,12 @@ void r_c_shortest_paths_dispatch
}
BGL_FORALL_VERTICES_T(i, g, Graph) {
- const std::list<Splabel>& list_labels_cur_vertex = vec_vertex_labels[i];
- csi_end = list_labels_cur_vertex.end();
- for( csi = list_labels_cur_vertex.begin(); csi != csi_end; ++csi )
+ std::list<Splabel>& list_labels_cur_vertex = vec_vertex_labels[i];
+ typename std::list<Splabel>::iterator si = list_labels_cur_vertex.begin();
+ const typename std::list<Splabel>::iterator si_end = list_labels_cur_vertex.end();
+ for(; si != si_end; ++si )
{
- assert ((*csi)->b_is_valid);
- (*csi)->b_is_valid = false;
- l_alloc.destroy( (*csi).get() );
- l_alloc.deallocate( (*csi).get(), 1 );
+ (*si).reset();
}
}
} // r_c_shortest_paths_dispatch
@@ -506,13 +474,13 @@ struct default_r_c_shortest_paths_visitor
void on_label_dominated( const Label&, const Graph& ) {}
template<class Label, class Graph>
void on_label_not_dominated( const Label&, const Graph& ) {}
- template<class Queue, class Graph>
+ template<class Queue, class Graph>
bool on_enter_loop(const Queue& queue, const Graph& graph) {return true;}
}; // default_r_c_shortest_paths_visitor
// default_r_c_shortest_paths_allocator
-typedef
+typedef
std::allocator<int> default_r_c_shortest_paths_allocator;
// default_r_c_shortest_paths_allocator
@@ -521,93 +489,93 @@ typedef
// first overload:
// - return all pareto-optimal solutions
// - specify Label_Allocator and Visitor arguments
-template<class Graph,
- class VertexIndexMap,
- class EdgeIndexMap,
- class Resource_Container,
- class Resource_Extension_Function,
- class Dominance_Function,
- class Label_Allocator,
+template<class Graph,
+ class VertexIndexMap,
+ class EdgeIndexMap,
+ class Resource_Container,
+ class Resource_Extension_Function,
+ class Dominance_Function,
+ class Label_Allocator,
class Visitor>
void r_c_shortest_paths
-( const Graph& g,
- const VertexIndexMap& vertex_index_map,
- const EdgeIndexMap& edge_index_map,
- typename graph_traits<Graph>::vertex_descriptor s,
- typename graph_traits<Graph>::vertex_descriptor t,
+( const Graph& g,
+ const VertexIndexMap& vertex_index_map,
+ const EdgeIndexMap& edge_index_map,
+ typename graph_traits<Graph>::vertex_descriptor s,
+ typename graph_traits<Graph>::vertex_descriptor t,
// each inner vector corresponds to a pareto-optimal path
- std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >&
- pareto_optimal_solutions,
- std::vector<Resource_Container>& pareto_optimal_resource_containers,
- // to initialize the first label/resource container
+ std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >&
+ pareto_optimal_solutions,
+ std::vector<Resource_Container>& pareto_optimal_resource_containers,
+ // to initialize the first label/resource container
// and to carry the type information
- const Resource_Container& rc,
- const Resource_Extension_Function& ref,
- const Dominance_Function& dominance,
+ const Resource_Container& rc,
+ const Resource_Extension_Function& ref,
+ const Dominance_Function& dominance,
// to specify the memory management strategy for the labels
- Label_Allocator la,
+ Label_Allocator la,
Visitor vis )
{
- r_c_shortest_paths_dispatch( g,
- vertex_index_map,
- edge_index_map,
- s,
- t,
- pareto_optimal_solutions,
- pareto_optimal_resource_containers,
- true,
- rc,
- ref,
- dominance,
- la,
+ r_c_shortest_paths_dispatch( g,
+ vertex_index_map,
+ edge_index_map,
+ s,
+ t,
+ pareto_optimal_solutions,
+ pareto_optimal_resource_containers,
+ true,
+ rc,
+ ref,
+ dominance,
+ la,
vis );
}
// second overload:
// - return only one pareto-optimal solution
// - specify Label_Allocator and Visitor arguments
-template<class Graph,
- class VertexIndexMap,
- class EdgeIndexMap,
- class Resource_Container,
- class Resource_Extension_Function,
- class Dominance_Function,
- class Label_Allocator,
+template<class Graph,
+ class VertexIndexMap,
+ class EdgeIndexMap,
+ class Resource_Container,
+ class Resource_Extension_Function,
+ class Dominance_Function,
+ class Label_Allocator,
class Visitor>
void r_c_shortest_paths
-( const Graph& g,
- const VertexIndexMap& vertex_index_map,
- const EdgeIndexMap& edge_index_map,
- typename graph_traits<Graph>::vertex_descriptor s,
- typename graph_traits<Graph>::vertex_descriptor t,
- std::vector<typename graph_traits<Graph>::edge_descriptor>&
- pareto_optimal_solution,
- Resource_Container& pareto_optimal_resource_container,
- // to initialize the first label/resource container
+( const Graph& g,
+ const VertexIndexMap& vertex_index_map,
+ const EdgeIndexMap& edge_index_map,
+ typename graph_traits<Graph>::vertex_descriptor s,
+ typename graph_traits<Graph>::vertex_descriptor t,
+ std::vector<typename graph_traits<Graph>::edge_descriptor>&
+ pareto_optimal_solution,
+ Resource_Container& pareto_optimal_resource_container,
+ // to initialize the first label/resource container
// and to carry the type information
- const Resource_Container& rc,
- const Resource_Extension_Function& ref,
- const Dominance_Function& dominance,
+ const Resource_Container& rc,
+ const Resource_Extension_Function& ref,
+ const Dominance_Function& dominance,
// to specify the memory management strategy for the labels
- Label_Allocator la,
+ Label_Allocator la,
Visitor vis )
{
// each inner vector corresponds to a pareto-optimal path
- std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >
+ std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >
pareto_optimal_solutions;
std::vector<Resource_Container> pareto_optimal_resource_containers;
- r_c_shortest_paths_dispatch( g,
- vertex_index_map,
- edge_index_map,
- s,
- t,
- pareto_optimal_solutions,
- pareto_optimal_resource_containers,
- false,
- rc,
- ref,
- dominance,
- la,
+ r_c_shortest_paths_dispatch( g,
+ vertex_index_map,
+ edge_index_map,
+ s,
+ t,
+ pareto_optimal_solutions,
+ pareto_optimal_resource_containers,
+ false,
+ rc,
+ ref,
+ dominance,
+ la,
vis );
if (!pareto_optimal_solutions.empty()) {
pareto_optimal_solution = pareto_optimal_solutions[0];
@@ -618,83 +586,83 @@ void r_c_shortest_paths
// third overload:
// - return all pareto-optimal solutions
// - use default Label_Allocator and Visitor
-template<class Graph,
- class VertexIndexMap,
- class EdgeIndexMap,
- class Resource_Container,
- class Resource_Extension_Function,
+template<class Graph,
+ class VertexIndexMap,
+ class EdgeIndexMap,
+ class Resource_Container,
+ class Resource_Extension_Function,
class Dominance_Function>
void r_c_shortest_paths
-( const Graph& g,
- const VertexIndexMap& vertex_index_map,
- const EdgeIndexMap& edge_index_map,
- typename graph_traits<Graph>::vertex_descriptor s,
- typename graph_traits<Graph>::vertex_descriptor t,
+( const Graph& g,
+ const VertexIndexMap& vertex_index_map,
+ const EdgeIndexMap& edge_index_map,
+ typename graph_traits<Graph>::vertex_descriptor s,
+ typename graph_traits<Graph>::vertex_descriptor t,
// each inner vector corresponds to a pareto-optimal path
- std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >&
- pareto_optimal_solutions,
- std::vector<Resource_Container>& pareto_optimal_resource_containers,
- // to initialize the first label/resource container
+ std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >&
+ pareto_optimal_solutions,
+ std::vector<Resource_Container>& pareto_optimal_resource_containers,
+ // to initialize the first label/resource container
// and to carry the type information
- const Resource_Container& rc,
- const Resource_Extension_Function& ref,
+ const Resource_Container& rc,
+ const Resource_Extension_Function& ref,
const Dominance_Function& dominance )
{
- r_c_shortest_paths_dispatch( g,
- vertex_index_map,
- edge_index_map,
- s,
- t,
- pareto_optimal_solutions,
- pareto_optimal_resource_containers,
- true,
- rc,
- ref,
- dominance,
- default_r_c_shortest_paths_allocator(),
+ r_c_shortest_paths_dispatch( g,
+ vertex_index_map,
+ edge_index_map,
+ s,
+ t,
+ pareto_optimal_solutions,
+ pareto_optimal_resource_containers,
+ true,
+ rc,
+ ref,
+ dominance,
+ default_r_c_shortest_paths_allocator(),
default_r_c_shortest_paths_visitor() );
}
// fourth overload:
// - return only one pareto-optimal solution
// - use default Label_Allocator and Visitor
-template<class Graph,
- class VertexIndexMap,
- class EdgeIndexMap,
- class Resource_Container,
- class Resource_Extension_Function,
+template<class Graph,
+ class VertexIndexMap,
+ class EdgeIndexMap,
+ class Resource_Container,
+ class Resource_Extension_Function,
class Dominance_Function>
void r_c_shortest_paths
-( const Graph& g,
- const VertexIndexMap& vertex_index_map,
- const EdgeIndexMap& edge_index_map,
- typename graph_traits<Graph>::vertex_descriptor s,
- typename graph_traits<Graph>::vertex_descriptor t,
- std::vector<typename graph_traits<Graph>::edge_descriptor>&
- pareto_optimal_solution,
- Resource_Container& pareto_optimal_resource_container,
- // to initialize the first label/resource container
+( const Graph& g,
+ const VertexIndexMap& vertex_index_map,
+ const EdgeIndexMap& edge_index_map,
+ typename graph_traits<Graph>::vertex_descriptor s,
+ typename graph_traits<Graph>::vertex_descriptor t,
+ std::vector<typename graph_traits<Graph>::edge_descriptor>&
+ pareto_optimal_solution,
+ Resource_Container& pareto_optimal_resource_container,
+ // to initialize the first label/resource container
// and to carry the type information
- const Resource_Container& rc,
- const Resource_Extension_Function& ref,
+ const Resource_Container& rc,
+ const Resource_Extension_Function& ref,
const Dominance_Function& dominance )
{
// each inner vector corresponds to a pareto-optimal path
- std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >
+ std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >
pareto_optimal_solutions;
std::vector<Resource_Container> pareto_optimal_resource_containers;
- r_c_shortest_paths_dispatch( g,
- vertex_index_map,
- edge_index_map,
- s,
- t,
- pareto_optimal_solutions,
- pareto_optimal_resource_containers,
- false,
- rc,
- ref,
- dominance,
- default_r_c_shortest_paths_allocator(),
+ r_c_shortest_paths_dispatch( g,
+ vertex_index_map,
+ edge_index_map,
+ s,
+ t,
+ pareto_optimal_solutions,
+ pareto_optimal_resource_containers,
+ false,
+ rc,
+ ref,
+ dominance,
+ default_r_c_shortest_paths_allocator(),
default_r_c_shortest_paths_visitor() );
if (!pareto_optimal_solutions.empty()) {
pareto_optimal_solution = pareto_optimal_solutions[0];
@@ -705,26 +673,26 @@ void r_c_shortest_paths
// check_r_c_path function
-template<class Graph,
- class Resource_Container,
+template<class Graph,
+ class Resource_Container,
class Resource_Extension_Function>
-void check_r_c_path( const Graph& g,
+void check_r_c_path( const Graph& g,
const std::vector
<typename graph_traits
- <Graph>::edge_descriptor>& ed_vec_path,
- const Resource_Container& initial_resource_levels,
- // if true, computed accumulated final resource levels must
+ <Graph>::edge_descriptor>& ed_vec_path,
+ const Resource_Container& initial_resource_levels,
+ // if true, computed accumulated final resource levels must
// be equal to desired_final_resource_levels
- // if false, computed accumulated final resource levels must
+ // if false, computed accumulated final resource levels must
// be less than or equal to desired_final_resource_levels
- bool b_result_must_be_equal_to_desired_final_resource_levels,
- const Resource_Container& desired_final_resource_levels,
- Resource_Container& actual_final_resource_levels,
- const Resource_Extension_Function& ref,
- bool& b_is_a_path_at_all,
- bool& b_feasible,
- bool& b_correctly_extended,
- typename graph_traits<Graph>::edge_descriptor&
+ bool b_result_must_be_equal_to_desired_final_resource_levels,
+ const Resource_Container& desired_final_resource_levels,
+ Resource_Container& actual_final_resource_levels,
+ const Resource_Extension_Function& ref,
+ bool& b_is_a_path_at_all,
+ bool& b_feasible,
+ bool& b_correctly_extended,
+ typename graph_traits<Graph>::edge_descriptor&
ed_last_extended_arc )
{
size_t i_size_ed_vec_path = ed_vec_path.size();
@@ -733,7 +701,7 @@ void check_r_c_path( const Graph& g,
b_feasible = true;
else
{
- if( i_size_ed_vec_path == 1
+ if( i_size_ed_vec_path == 1
|| target( ed_vec_path[0], g ) == source( ed_vec_path[1], g ) )
buf_path = ed_vec_path;
else
@@ -758,21 +726,21 @@ void check_r_c_path( const Graph& g,
for( size_t i = 0; i < i_size_ed_vec_path; ++i )
{
ed_last_extended_arc = buf_path[i];
- b_feasible = ref( g,
- actual_final_resource_levels,
- current_resource_levels,
+ b_feasible = ref( g,
+ actual_final_resource_levels,
+ current_resource_levels,
buf_path[i] );
current_resource_levels = actual_final_resource_levels;
if( !b_feasible )
return;
}
if( b_result_must_be_equal_to_desired_final_resource_levels )
- b_correctly_extended =
- actual_final_resource_levels == desired_final_resource_levels ?
+ b_correctly_extended =
+ actual_final_resource_levels == desired_final_resource_levels ?
true : false;
else
{
- if( actual_final_resource_levels < desired_final_resource_levels
+ if( actual_final_resource_levels < desired_final_resource_levels
|| actual_final_resource_levels == desired_final_resource_levels )
b_correctly_extended = true;
}
diff --git a/boost/graph/random_spanning_tree.hpp b/boost/graph/random_spanning_tree.hpp
index 76dc7f2b9a..ee23c5e1ee 100644
--- a/boost/graph/random_spanning_tree.hpp
+++ b/boost/graph/random_spanning_tree.hpp
@@ -95,12 +95,26 @@ namespace boost {
using namespace boost::graph::keywords;
typedef bgl_named_params<P, T, R> params_type;
BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params)
- random_spanning_tree(g,
- gen,
- arg_pack[_root_vertex | *vertices(g).first],
- arg_pack[_predecessor_map],
- arg_pack[_weight_map | static_property_map<double>(1.)],
- boost::detail::make_color_map_from_arg_pack(g, arg_pack));
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+ vertex_descriptor default_vertex = *vertices(g).first;
+ vertex_descriptor start_vertex = arg_pack[_root_vertex | default_vertex];
+ typename boost::parameter::binding<
+ arg_pack_type,
+ boost::graph::keywords::tag::predecessor_map
+ >::type pred_map = arg_pack[_predecessor_map];
+ static_property_map<double> default_weight_map(1.);
+ typename boost::parameter::value_type<
+ arg_pack_type,
+ boost::graph::keywords::tag::weight_map,
+ static_property_map<double>
+ >::type e_w_map = arg_pack[_weight_map | default_weight_map];
+ typename boost::detail::map_maker<
+ Graph,
+ arg_pack_type,
+ boost::graph::keywords::tag::color_map,
+ boost::default_color_type
+ >::map_type c_map = boost::detail::make_color_map_from_arg_pack(g, arg_pack);
+ random_spanning_tree(g, gen, start_vertex, pred_map, e_w_map, c_map);
}
}
diff --git a/boost/graph/relax.hpp b/boost/graph/relax.hpp
index e3866df484..ea9521b237 100644
--- a/boost/graph/relax.hpp
+++ b/boost/graph/relax.hpp
@@ -76,6 +76,37 @@ namespace boost {
} else
return false;
}
+
+ template <class Graph, class WeightMap,
+ class PredecessorMap, class DistanceMap,
+ class BinaryFunction, class BinaryPredicate>
+ bool relax_target(typename graph_traits<Graph>::edge_descriptor e,
+ const Graph& g, const WeightMap& w,
+ PredecessorMap& p, DistanceMap& d,
+ const BinaryFunction& combine, const BinaryPredicate& compare)
+ {
+ typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
+ typedef typename property_traits<DistanceMap>::value_type D;
+ typedef typename property_traits<WeightMap>::value_type W;
+ const Vertex u = source(e, g);
+ const Vertex v = target(e, g);
+ const D d_u = get(d, u);
+ const D d_v = get(d, v);
+ const W& w_e = get(w, e);
+
+ // The seemingly redundant comparisons after the distance puts are to
+ // ensure that extra floating-point precision in x87 registers does not
+ // lead to relax() returning true when the distance did not actually
+ // change.
+ if (compare(combine(d_u, w_e), d_v)) {
+ put(d, v, combine(d_u, w_e));
+ if (compare(get(d, v), d_v)) {
+ put(p, v, u);
+ return true;
+ }
+ }
+ return false;
+ }
template <class Graph, class WeightMap,
class PredecessorMap, class DistanceMap>
diff --git a/boost/graph/rmat_graph_generator.hpp b/boost/graph/rmat_graph_generator.hpp
index f083fc5558..a96887fbd6 100644
--- a/boost/graph/rmat_graph_generator.hpp
+++ b/boost/graph/rmat_graph_generator.hpp
@@ -20,6 +20,7 @@
#include <boost/random/uniform_int.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/graph/graph_traits.hpp>
+#include <boost/graph/detail/mpi_include.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/type_traits/is_same.hpp>
// #include <boost/test/floating_point_comparison.hpp>
@@ -588,8 +589,6 @@ namespace boost {
} // end namespace boost
-#ifdef BOOST_GRAPH_USE_MPI
-#include <boost/graph/distributed/rmat_graph_generator.hpp>
-#endif // BOOST_GRAPH_USE_MPI
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/rmat_graph_generator.hpp>)
#endif // BOOST_GRAPH_RMAT_GENERATOR_HPP
diff --git a/boost/graph/sloan_ordering.hpp b/boost/graph/sloan_ordering.hpp
index 88ad1b297f..afc634a921 100644
--- a/boost/graph/sloan_ordering.hpp
+++ b/boost/graph/sloan_ordering.hpp
@@ -1,7 +1,8 @@
//
//=======================================================================
// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch)
-// ETH Zurich, Center of Structure Technologies (www.imes.ethz.ch/st)
+// ETH Zurich, Center of Structure Technologies
+// (https://web.archive.org/web/20050307090307/http://www.structures.ethz.ch/)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
diff --git a/boost/graph/stanford_graph.hpp b/boost/graph/stanford_graph.hpp
index 01431737bf..d9b451a8f3 100644
--- a/boost/graph/stanford_graph.hpp
+++ b/boost/graph/stanford_graph.hpp
@@ -10,7 +10,6 @@
#define BOOST_GRAPH_SGB_GRAPH_HPP
#include <boost/config.hpp>
-#include <boost/iterator.hpp>
#include <boost/operators.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/graph_traits.hpp>
diff --git a/boost/graph/stoer_wagner_min_cut.hpp b/boost/graph/stoer_wagner_min_cut.hpp
index eb5998c710..357f170840 100644
--- a/boost/graph/stoer_wagner_min_cut.hpp
+++ b/boost/graph/stoer_wagner_min_cut.hpp
@@ -215,9 +215,10 @@ namespace graph {
typename boost::result_of<gen_type(const UndirectedGraph&, const ArgPack&)>::type pq = gen(g, arg_pack);
+ boost::dummy_property_map dummy_prop;
return boost::stoer_wagner_min_cut(g,
weights,
- arg_pack [_parity_map | boost::dummy_property_map()],
+ arg_pack [_parity_map | dummy_prop],
boost::detail::make_property_map_from_arg_pack_gen<tag::vertex_assignment_map, vertex_descriptor>(vertex_descriptor())(g, arg_pack),
pq,
boost::detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index)
diff --git a/boost/graph/strong_components.hpp b/boost/graph/strong_components.hpp
index f1bd56d6f7..67dbfdd806 100644
--- a/boost/graph/strong_components.hpp
+++ b/boost/graph/strong_components.hpp
@@ -18,6 +18,7 @@
#include <boost/type_traits/conversion_traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/graph/overloading.hpp>
+#include <boost/graph/detail/mpi_include.hpp>
#include <boost/concept/assert.hpp>
namespace boost {
@@ -336,8 +337,6 @@ namespace boost {
} // namespace boost
-#ifdef BOOST_GRAPH_USE_MPI
-# include <boost/graph/distributed/strong_components.hpp>
-#endif
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/strong_components.hpp>)
#endif // BOOST_GRAPH_STRONG_COMPONENTS_HPP
diff --git a/boost/graph/subgraph.hpp b/boost/graph/subgraph.hpp
index 22706bc617..3d068a5c36 100644
--- a/boost/graph/subgraph.hpp
+++ b/boost/graph/subgraph.hpp
@@ -131,12 +131,24 @@ public:
// copy constructor
subgraph(const subgraph& x)
- : m_parent(x.m_parent), m_edge_counter(x.m_edge_counter)
- , m_global_vertex(x.m_global_vertex), m_global_edge(x.m_global_edge)
+ : m_parent(x.m_parent), m_edge_counter(0)
{
if(x.is_root())
{
- m_graph = x.m_graph;
+ m_graph = x.m_graph;
+ m_edge_counter = x.m_edge_counter;
+ m_global_vertex = x.m_global_vertex;
+ m_global_edge = x.m_global_edge;
+ }
+ else
+ {
+ get_property(*this) = get_property(x);
+ typename subgraph<Graph>::vertex_iterator vi,vi_end;
+ boost::tie(vi, vi_end) = vertices(x);
+ for(; vi != vi_end; ++vi)
+ {
+ add_vertex(x.local_to_global(*vi), *this);
+ }
}
// Do a deep copy (recursive).
// Only the root graph is copied, the subgraphs contain
@@ -144,16 +156,10 @@ public:
typename subgraph<Graph>::children_iterator i,i_end;
boost::tie(i,i_end) = x.children();
for(; i != i_end; ++i)
- {
- subgraph<Graph> child = this->create_subgraph();
- child = *i;
- vertex_iterator vi,vi_end;
- boost::tie(vi,vi_end) = vertices(*i);
- for (;vi!=vi_end;++vi)
- {
- add_vertex(*vi,child);
- }
- }
+ {
+ m_children.push_back(new subgraph<Graph>(*i));
+ m_children.back()->m_parent = this;
+ }
}
@@ -371,46 +377,54 @@ typename subgraph<G>::vertex_descriptor
add_vertex(typename subgraph<G>::vertex_descriptor u_global,
subgraph<G>& g)
{
- BOOST_ASSERT(!g.is_root());
- typename subgraph<G>::vertex_descriptor u_local, v_global;
- typename subgraph<G>::edge_descriptor e_global;
-
- u_local = add_vertex(g.m_graph);
- g.m_global_vertex.push_back(u_global);
- g.m_local_vertex[u_global] = u_local;
-
- subgraph<G>& r = g.root();
-
- // remember edge global and local maps
- {
- typename subgraph<G>::out_edge_iterator ei, ei_end;
- for (boost::tie(ei, ei_end) = out_edges(u_global, r);
- ei != ei_end; ++ei) {
- e_global = *ei;
- v_global = target(e_global, r);
- if (g.find_vertex(v_global).second == true)
- g.local_add_edge(u_local, g.global_to_local(v_global), e_global);
- }
- }
- if (is_directed(g)) { // not necessary for undirected graph
- typename subgraph<G>::vertex_iterator vi, vi_end;
- typename subgraph<G>::out_edge_iterator ei, ei_end;
- for(boost::tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) {
- v_global = *vi;
- if (v_global == u_global)
- continue; // don't insert self loops twice!
- if (!g.find_vertex(v_global).second)
- continue; // not a subgraph vertex => try next one
- for(boost::tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end; ++ei) {
- e_global = *ei;
- if(target(e_global, r) == u_global) {
- g.local_add_edge(g.global_to_local(v_global), u_local, e_global);
- }
+ BOOST_ASSERT(!g.is_root());
+ typename subgraph<G>::vertex_descriptor u_local;
+ bool exists_local;
+ boost::tie(u_local, exists_local) = g.find_vertex(u_global);
+
+ if (!exists_local) {
+ typename subgraph<G>::vertex_descriptor v_global;
+ typename subgraph<G>::edge_descriptor e_global;
+ // call recursion for parent subgraph
+ if (!g.parent().is_root())
+ add_vertex(u_global, g.parent());
+
+ u_local = add_vertex(g.m_graph);
+ g.m_global_vertex.push_back(u_global);
+ g.m_local_vertex[u_global] = u_local;
+
+ subgraph<G>& r = g.root();
+
+ // remember edge global and local maps
+ {
+ typename subgraph<G>::out_edge_iterator ei, ei_end;
+ for (boost::tie(ei, ei_end) = out_edges(u_global, r);
+ ei != ei_end; ++ei) {
+ e_global = *ei;
+ v_global = target(e_global, r);
+ if (g.find_vertex(v_global).second == true)
+ g.local_add_edge(u_local, g.global_to_local(v_global), e_global);
}
- }
- }
-
- return u_local;
+ }
+ if (is_directed(g)) { // not necessary for undirected graph
+ typename subgraph<G>::vertex_iterator vi, vi_end;
+ typename subgraph<G>::out_edge_iterator ei, ei_end;
+ for(boost::tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) {
+ v_global = *vi;
+ if (v_global == u_global)
+ continue; // don't insert self loops twice!
+ if (!g.find_vertex(v_global).second)
+ continue; // not a subgraph vertex => try next one
+ for(boost::tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end; ++ei) {
+ e_global = *ei;
+ if(target(e_global, r) == u_global) {
+ g.local_add_edge(g.global_to_local(v_global), u_local, e_global);
+ }
+ }
+ }
+ }
+ }
+ return u_local;
}
// NOTE: Descriptors are local unless otherwise noted.
diff --git a/boost/graph/successive_shortest_path_nonnegative_weights.hpp b/boost/graph/successive_shortest_path_nonnegative_weights.hpp
index 72b1512c16..6a3aeb168e 100644
--- a/boost/graph/successive_shortest_path_nonnegative_weights.hpp
+++ b/boost/graph/successive_shortest_path_nonnegative_weights.hpp
@@ -1,6 +1,6 @@
//=======================================================================
// Copyright 2013 University of Warsaw.
-// Authors: Piotr Wygocki
+// Authors: Piotr Wygocki
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -11,7 +11,7 @@
// by Ahuja, Magnanti, Orlin.
#ifndef BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP
-#define BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP
+#define BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP
#include <numeric>
@@ -19,7 +19,6 @@
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/pending/indirect_cmp.hpp>
-#include <boost/pending/relaxed_heap.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/iteration_macros.hpp>
@@ -29,9 +28,9 @@ namespace boost {
namespace detail {
-
+
template <class Graph, class Weight, class Distance, class Reversed>
-class MapReducedWeight :
+class MapReducedWeight :
public put_get_helper<typename property_traits<Weight>::value_type, MapReducedWeight<Graph, Weight, Distance, Reversed> > {
typedef graph_traits<Graph> gtraits;
public:
@@ -39,11 +38,11 @@ public:
typedef typename property_traits<Weight>::value_type value_type;
typedef value_type reference;
typedef typename gtraits::edge_descriptor key_type;
- MapReducedWeight(const Graph & g, Weight w, Distance d, Reversed r) :
+ MapReducedWeight(const Graph & g, Weight w, Distance d, Reversed r) :
g_(g), weight_(w), distance_(d), rev_(r) {}
reference operator[](key_type v) const {
- return get(distance_, source(v, g_)) - get(distance_,target(v, g_)) + get(weight_, v);
+ return get(distance_, source(v, g_)) - get(distance_,target(v, g_)) + get(weight_, v);
}
private:
const Graph & g_;
@@ -53,7 +52,7 @@ private:
};
template <class Graph, class Weight, class Distance, class Reversed>
-MapReducedWeight<Graph, Weight, Distance, Reversed>
+MapReducedWeight<Graph, Weight, Distance, Reversed>
make_mapReducedWeight(const Graph & g, Weight w, Distance d, Reversed r) {
return MapReducedWeight<Graph, Weight, Distance, Reversed>(g, w, d, r);
}
@@ -63,21 +62,21 @@ make_mapReducedWeight(const Graph & g, Weight w, Distance d, Reversed r) {
template <class Graph, class Capacity, class ResidualCapacity, class Reversed, class Pred, class Weight, class Distance, class Distance2, class VertexIndex>
void successive_shortest_path_nonnegative_weights(
- const Graph &g,
- typename graph_traits<Graph>::vertex_descriptor s,
+ const Graph &g,
+ typename graph_traits<Graph>::vertex_descriptor s,
typename graph_traits<Graph>::vertex_descriptor t,
Capacity capacity,
ResidualCapacity residual_capacity,
- Weight weight,
+ Weight weight,
Reversed rev,
VertexIndex index,
- Pred pred,
+ Pred pred,
Distance distance,
Distance2 distance_prev) {
filtered_graph<const Graph, is_residual_edge<ResidualCapacity> >
gres = detail::residual_graph(g, residual_capacity);
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
-
+
BGL_FORALL_EDGES_T(e, g, Graph) {
put(residual_capacity, e, get(capacity, e));
}
@@ -90,7 +89,7 @@ void successive_shortest_path_nonnegative_weights(
BGL_FORALL_VERTICES_T(v, g, Graph) {
put(pred, v, edge_descriptor());
}
- dijkstra_shortest_paths(gres, s,
+ dijkstra_shortest_paths(gres, s,
weight_map(detail::make_mapReducedWeight(gres, weight, distance_prev, rev)).
distance_map(distance).
vertex_index_map(index).
@@ -113,8 +112,8 @@ namespace detail {
template <class Graph, class Capacity, class ResidualCapacity, class Weight, class Reversed, class Pred, class Distance, class Distance2, class VertexIndex>
void successive_shortest_path_nonnegative_weights_dispatch3(
- const Graph &g,
- typename graph_traits<Graph>::vertex_descriptor s,
+ const Graph &g,
+ typename graph_traits<Graph>::vertex_descriptor s,
typename graph_traits<Graph>::vertex_descriptor t,
Capacity capacity,
ResidualCapacity residual_capacity,
@@ -130,8 +129,8 @@ void successive_shortest_path_nonnegative_weights_dispatch3(
//setting default distance map
template <class Graph, class Capacity, class ResidualCapacity, class Weight, class Reversed, class Pred, class Distance, class VertexIndex>
void successive_shortest_path_nonnegative_weights_dispatch3(
- Graph &g,
- typename graph_traits<Graph>::vertex_descriptor s,
+ Graph &g,
+ typename graph_traits<Graph>::vertex_descriptor s,
typename graph_traits<Graph>::vertex_descriptor t,
Capacity capacity,
ResidualCapacity residual_capacity,
@@ -151,8 +150,8 @@ void successive_shortest_path_nonnegative_weights_dispatch3(
template <class Graph, class P, class T, class R, class Capacity, class ResidualCapacity, class Weight, class Reversed, class Pred, class Distance, class VertexIndex>
void successive_shortest_path_nonnegative_weights_dispatch2(
- Graph &g,
- typename graph_traits<Graph>::vertex_descriptor s,
+ Graph &g,
+ typename graph_traits<Graph>::vertex_descriptor s,
typename graph_traits<Graph>::vertex_descriptor t,
Capacity capacity,
ResidualCapacity residual_capacity,
@@ -168,8 +167,8 @@ void successive_shortest_path_nonnegative_weights_dispatch2(
//setting default distance map
template <class Graph, class P, class T, class R, class Capacity, class ResidualCapacity, class Weight, class Reversed, class Pred, class VertexIndex>
void successive_shortest_path_nonnegative_weights_dispatch2(
- Graph &g,
- typename graph_traits<Graph>::vertex_descriptor s,
+ Graph &g,
+ typename graph_traits<Graph>::vertex_descriptor s,
typename graph_traits<Graph>::vertex_descriptor t,
Capacity capacity,
ResidualCapacity residual_capacity,
@@ -177,7 +176,7 @@ void successive_shortest_path_nonnegative_weights_dispatch2(
Reversed rev,
VertexIndex index,
Pred pred,
- param_not_found,
+ param_not_found,
const bgl_named_params<P, T, R>& params) {
typedef typename property_traits<Weight>::value_type D;
@@ -190,12 +189,12 @@ void successive_shortest_path_nonnegative_weights_dispatch2(
template <class Graph, class P, class T, class R, class Capacity, class ResidualCapacity, class Weight, class Reversed, class Pred, class VertexIndex>
void successive_shortest_path_nonnegative_weights_dispatch1(
- Graph &g,
- typename graph_traits<Graph>::vertex_descriptor s,
+ Graph &g,
+ typename graph_traits<Graph>::vertex_descriptor s,
typename graph_traits<Graph>::vertex_descriptor t,
Capacity capacity,
ResidualCapacity residual_capacity,
- Weight weight,
+ Weight weight,
Reversed rev,
VertexIndex index,
Pred pred,
@@ -207,12 +206,12 @@ void successive_shortest_path_nonnegative_weights_dispatch1(
//setting default predecessors map
template <class Graph, class P, class T, class R, class Capacity, class ResidualCapacity, class Weight, class Reversed, class VertexIndex>
void successive_shortest_path_nonnegative_weights_dispatch1(
- Graph &g,
- typename graph_traits<Graph>::vertex_descriptor s,
+ Graph &g,
+ typename graph_traits<Graph>::vertex_descriptor s,
typename graph_traits<Graph>::vertex_descriptor t,
Capacity capacity,
ResidualCapacity residual_capacity,
- Weight weight,
+ Weight weight,
Reversed rev,
VertexIndex index,
param_not_found,
@@ -220,9 +219,9 @@ void successive_shortest_path_nonnegative_weights_dispatch1(
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
std::vector<edge_descriptor> pred_vec(num_vertices(g));
- successive_shortest_path_nonnegative_weights_dispatch2(g, s, t, capacity, residual_capacity, weight, rev, index,
+ successive_shortest_path_nonnegative_weights_dispatch2(g, s, t, capacity, residual_capacity, weight, rev, index,
make_iterator_property_map(pred_vec.begin(), index),
- get_param(params, vertex_distance), params);
+ get_param(params, vertex_distance), params);
}
}//detail
@@ -230,26 +229,26 @@ void successive_shortest_path_nonnegative_weights_dispatch1(
template <class Graph, class P, class T, class R>
void successive_shortest_path_nonnegative_weights(
- Graph &g,
- typename graph_traits<Graph>::vertex_descriptor s,
+ Graph &g,
+ typename graph_traits<Graph>::vertex_descriptor s,
typename graph_traits<Graph>::vertex_descriptor t,
const bgl_named_params<P, T, R>& params) {
-
- return detail::successive_shortest_path_nonnegative_weights_dispatch1(g, s, t,
+
+ return detail::successive_shortest_path_nonnegative_weights_dispatch1(g, s, t,
choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
- choose_pmap(get_param(params, edge_residual_capacity),
+ choose_pmap(get_param(params, edge_residual_capacity),
g, edge_residual_capacity),
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
- get_param(params, vertex_predecessor),
+ get_param(params, vertex_predecessor),
params);
}
template <class Graph>
void successive_shortest_path_nonnegative_weights(
Graph &g,
- typename graph_traits<Graph>::vertex_descriptor s,
+ typename graph_traits<Graph>::vertex_descriptor s,
typename graph_traits<Graph>::vertex_descriptor t) {
bgl_named_params<int, buffer_param_t> params(0);
successive_shortest_path_nonnegative_weights(g, s, t, params);
@@ -258,4 +257,3 @@ void successive_shortest_path_nonnegative_weights(
}//boost
#endif /* BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP */
-
diff --git a/boost/graph/two_bit_color_map.hpp b/boost/graph/two_bit_color_map.hpp
index 3d55eabc70..077b7cb342 100644
--- a/boost/graph/two_bit_color_map.hpp
+++ b/boost/graph/two_bit_color_map.hpp
@@ -15,6 +15,7 @@
#include <boost/property_map/property_map.hpp>
#include <boost/graph/properties.hpp>
+#include <boost/graph/detail/mpi_include.hpp>
#include <boost/shared_array.hpp>
#include <boost/config.hpp>
#include <boost/assert.hpp>
@@ -102,8 +103,6 @@ make_two_bit_color_map(std::size_t n, const IndexMap& index_map)
} // end namespace boost
-#endif // BOOST_TWO_BIT_COLOR_MAP_HPP
+#include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/two_bit_color_map.hpp>)
-#ifdef BOOST_GRAPH_USE_MPI
-# include <boost/graph/distributed/two_bit_color_map.hpp>
-#endif
+#endif // BOOST_TWO_BIT_COLOR_MAP_HPP
diff --git a/boost/graph/vector_as_graph.hpp b/boost/graph/vector_as_graph.hpp
index b771eaf7fd..1c3890224f 100644
--- a/boost/graph/vector_as_graph.hpp
+++ b/boost/graph/vector_as_graph.hpp
@@ -18,7 +18,7 @@
#include <utility>
#include <vector>
#include <cstddef>
-#include <boost/iterator.hpp>
+#include <iterator>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/range/irange.hpp>
#include <boost/graph/graph_traits.hpp>
@@ -110,12 +110,15 @@ namespace boost {
// need rewrite this using boost::iterator_adaptor
template <class V, class Iter>
class val_out_edge_iterator
- : public boost::iterator<std::input_iterator_tag, std::pair<V,V>,
- std::ptrdiff_t, std::pair<V,V>*, const std::pair<V,V> >
{
typedef val_out_edge_iterator self;
typedef std::pair<V,V> Edge;
public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::pair<V,V> value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::pair<V,V>* pointer;
+ typedef const std::pair<V,V> reference;
val_out_edge_iterator() { }
val_out_edge_iterator(V s, Iter i) : _source(s), _iter(i) { }
Edge operator*() const { return Edge(_source, *_iter); }
diff --git a/boost/graph/wavefront.hpp b/boost/graph/wavefront.hpp
index 4d9c909c70..3873ac718c 100644
--- a/boost/graph/wavefront.hpp
+++ b/boost/graph/wavefront.hpp
@@ -1,7 +1,8 @@
//
//=======================================================================
// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch)
-// ETH Zurich, Center of Structure Technologies (www.imes.ethz.ch/st)
+// ETH Zurich, Center of Structure Technologies
+// (https://web.archive.org/web/20050307090307/http://www.structures.ethz.ch/)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
diff --git a/boost/hana/basic_tuple.hpp b/boost/hana/basic_tuple.hpp
index 3e624694e0..c384c3a235 100644
--- a/boost/hana/basic_tuple.hpp
+++ b/boost/hana/basic_tuple.hpp
@@ -42,10 +42,18 @@ BOOST_HANA_NAMESPACE_BEGIN
struct from_other { };
template <typename Indices, typename ...Xn>
+#ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
+ struct __declspec(empty_bases) basic_tuple_impl;
+#else
struct basic_tuple_impl;
+#endif
template <std::size_t ...n, typename ...Xn>
+#ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
+ struct __declspec(empty_bases) basic_tuple_impl<std::index_sequence<n...>, Xn...>
+#else
struct basic_tuple_impl<std::index_sequence<n...>, Xn...>
+#endif
: detail::ebo<bti<n>, Xn>...
{
static constexpr std::size_t size_ = sizeof...(Xn);
@@ -193,7 +201,7 @@ BOOST_HANA_NAMESPACE_BEGIN
static constexpr auto apply(Xs&& xs, N const&) {
constexpr std::size_t len = detail::decay<Xs>::type::size_;
return drop_front_helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence<
- N::value < len ? len - N::value : 0
+ (N::value < len) ? len - N::value : 0
>{});
}
};
diff --git a/boost/hana/config.hpp b/boost/hana/config.hpp
index 35e97a0a50..96c13de692 100644
--- a/boost/hana/config.hpp
+++ b/boost/hana/config.hpp
@@ -20,7 +20,29 @@ Distributed under the Boost Software License, Version 1.0.
#if defined(_MSC_VER) && !defined(__clang__) // MSVC
// This must be checked first, because otherwise it produces a fatal
// error due to unrecognized #warning directives used below.
-# pragma message("Warning: the native Microsoft compiler is not supported due to lack of proper C++14 support.")
+
+# if _MSC_VER < 1915
+# pragma message("Warning: the native Microsoft compiler is not supported due to lack of proper C++14 support.")
+# else
+ // 1. Active issues
+ // Multiple copy/move ctors
+# define BOOST_HANA_WORKAROUND_MSVC_MULTIPLECTOR_106654
+
+ // 2. Issues fixed in the development branch of MSVC
+ // Forward declaration of class template member function returning decltype(auto)
+# define BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
+
+ // 3. Issues fixed conditionally
+ // Requires __declspec(empty_bases)
+ // Empty base optimization
+# define BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
+
+ // Requires /experimental:preprocessor
+ // Variadic macro expansion
+# if !defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL
+# define BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
+# endif
+# endif
#elif defined(__clang__) && defined(_MSC_VER) // Clang-cl (Clang for Windows)
@@ -40,7 +62,7 @@ Distributed under the Boost Software License, Version 1.0.
# if __apple_build_version__ >= 6020049
# define BOOST_HANA_CONFIG_CLANG BOOST_HANA_CONFIG_VERSION(3, 6, 0)
# else
-# warning "Versions of Apple's Clang prior to the one shipped with Xcode 6.3 are not supported by Hana."
+# warning "Versions of Apple's Clang prior to the one shipped with Xcode 6.3 are known not to be able to compile Hana."
# endif
#elif defined(__clang__) // genuine Clang
@@ -72,7 +94,9 @@ Distributed under the Boost Software License, Version 1.0.
//////////////////////////////////////////////////////////////////////////////
#if (__cplusplus < 201400)
# if defined(_MSC_VER)
-# pragma message("Warning: Your compiler doesn't provide C++14 or higher capabilities. Try adding the compiler flag '-std=c++14' or '-std=c++1y'.")
+# if _MSC_VER < 1915
+# pragma message("Warning: Your compiler doesn't provide C++14 or higher capabilities. Try adding the compiler flag '-std=c++14' or '-std=c++1y'.")
+# endif
# else
# warning "Your compiler doesn't provide C++14 or higher capabilities. Try adding the compiler flag '-std=c++14' or '-std=c++1y'."
# endif
diff --git a/boost/hana/detail/integral_constant.hpp b/boost/hana/detail/integral_constant.hpp
index 6fa7735164..72a40dacae 100644
--- a/boost/hana/detail/integral_constant.hpp
+++ b/boost/hana/detail/integral_constant.hpp
@@ -231,7 +231,11 @@ BOOST_HANA_NAMESPACE_BEGIN
};
#else
template <typename T, T v>
+#ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
+ struct __declspec(empty_bases) integral_constant
+#else
struct integral_constant
+#endif
: std::integral_constant<T, v>
, detail::operators::adl<integral_constant<T, v>>
{
diff --git a/boost/hana/detail/preprocessor.hpp b/boost/hana/detail/preprocessor.hpp
index 6a141187e7..4487ad8daf 100644
--- a/boost/hana/detail/preprocessor.hpp
+++ b/boost/hana/detail/preprocessor.hpp
@@ -22,7 +22,12 @@ Distributed under the Boost Software License, Version 1.0.
//! @ingroup group-details
//! Expands to its first argument.
+#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
+#define BOOST_HANA_PP_FRONT(...) BOOST_HANA_PP_FRONT_IMPL_I(__VA_ARGS__)
+#define BOOST_HANA_PP_FRONT_IMPL_I(...) BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_FRONT_IMPL(__VA_ARGS__, ),)
+#else
#define BOOST_HANA_PP_FRONT(...) BOOST_HANA_PP_FRONT_IMPL(__VA_ARGS__, )
+#endif
#define BOOST_HANA_PP_FRONT_IMPL(e0, ...) e0
//! @ingroup group-details
diff --git a/boost/hana/detail/struct_macros.hpp b/boost/hana/detail/struct_macros.hpp
index e99ab4fac8..8298de67d6 100644
--- a/boost/hana/detail/struct_macros.hpp
+++ b/boost/hana/detail/struct_macros.hpp
@@ -67,8 +67,13 @@ BOOST_HANA_NAMESPACE_BEGIN namespace struct_detail {
//!
//! Specifically, `BOOST_HANA_PP_NARG(x1, ..., xn)` expands to `n`. It is
//! an error to call this macro with 0 arguments.
+#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
+#define BOOST_HANA_PP_NARG(...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_NARG_IMPL(__VA_ARGS__, 40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,),)
+#else
#define BOOST_HANA_PP_NARG(...) \
BOOST_HANA_PP_NARG_IMPL(__VA_ARGS__, 40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,)
+#endif
#define BOOST_HANA_PP_NARG_IMPL(e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15,e16,e17,e18,e19,e20,e21,e22,e23,e24,e25,e26,e27,e28,e29,e30,e31,e32,e33,e34,e35,e36,e37,e38,e39,e40, N, ...) N
@@ -80,8 +85,14 @@ BOOST_HANA_NAMESPACE_BEGIN namespace struct_detail {
#define BOOST_HANA_PP_BACK(...) \
BOOST_HANA_PP_BACK_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
+#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
+#define BOOST_HANA_PP_BACK_IMPL(N, ...) BOOST_HANA_PP_BACK_IMPL_I(N, __VA_ARGS__)
+#define BOOST_HANA_PP_BACK_IMPL_I(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_BACK_IMPL_, N)(__VA_ARGS__),)
+#else
#define BOOST_HANA_PP_BACK_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_BACK_IMPL_, N)(__VA_ARGS__)
+#endif
#define BOOST_HANA_PP_BACK_IMPL_1(e1) e1
@@ -173,8 +184,14 @@ BOOST_HANA_NAMESPACE_BEGIN namespace struct_detail {
#define BOOST_HANA_PP_DROP_BACK(...) \
BOOST_HANA_PP_DROP_BACK_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
+#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
+#define BOOST_HANA_PP_DROP_BACK_IMPL(N, ...) BOOST_HANA_PP_DROP_BACK_IMPL_I(N, __VA_ARGS__)
+#define BOOST_HANA_PP_DROP_BACK_IMPL_I(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_DROP_BACK_IMPL_, N)(__VA_ARGS__),)
+#else
#define BOOST_HANA_PP_DROP_BACK_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_DROP_BACK_IMPL_, N)(__VA_ARGS__)
+#endif
#define BOOST_HANA_PP_DROP_BACK_IMPL_1(e1)
@@ -271,8 +288,14 @@ struct BOOST_HANA_ADAPT_STRUCT_must_be_called_in_the_global_namespace;
static_assert(true, "force the usage of a trailing semicolon") \
/**/
+#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
+#define BOOST_HANA_ADAPT_STRUCT_IMPL(N, ...) BOOST_HANA_ADAPT_STRUCT_IMPL_I(N, __VA_ARGS__)
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_I(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_STRUCT_IMPL_, N)(__VA_ARGS__),)
+#else
#define BOOST_HANA_ADAPT_STRUCT_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_STRUCT_IMPL_, N)(__VA_ARGS__)
+#endif
#define BOOST_HANA_ADAPT_STRUCT_IMPL_1(TYPE ) \
@@ -1109,8 +1132,14 @@ struct BOOST_HANA_ADAPT_ADT_must_be_called_in_the_global_namespace;
static_assert(true, "force the usage of a trailing semicolon") \
/**/
+#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
+#define BOOST_HANA_ADAPT_ADT_IMPL(N, ...) BOOST_HANA_ADAPT_ADT_IMPL_I(N, __VA_ARGS__)
+#define BOOST_HANA_ADAPT_ADT_IMPL_I(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_ADT_IMPL_, N)(__VA_ARGS__),)
+#else
#define BOOST_HANA_ADAPT_ADT_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_ADT_IMPL_, N)(__VA_ARGS__)
+#endif
#define BOOST_HANA_ADAPT_ADT_IMPL_1(TYPE ) \
@@ -1981,8 +2010,14 @@ struct BOOST_HANA_ADAPT_ADT_must_be_called_in_the_global_namespace;
#define BOOST_HANA_DEFINE_STRUCT(...) \
BOOST_HANA_DEFINE_STRUCT_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
+#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
+#define BOOST_HANA_DEFINE_STRUCT_IMPL(N, ...) BOOST_HANA_DEFINE_STRUCT_IMPL_I(N, __VA_ARGS__)
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_I(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_CONCAT(BOOST_HANA_DEFINE_STRUCT_IMPL_, N)(__VA_ARGS__),)
+#else
#define BOOST_HANA_DEFINE_STRUCT_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_DEFINE_STRUCT_IMPL_, N)(__VA_ARGS__)
+#endif
#define BOOST_HANA_DEFINE_STRUCT_IMPL_1(TYPE ) \
diff --git a/boost/hana/detail/variadic/reverse_apply.hpp b/boost/hana/detail/variadic/reverse_apply.hpp
index b276fa4177..a1f71ff53c 100644
--- a/boost/hana/detail/variadic/reverse_apply.hpp
+++ b/boost/hana/detail/variadic/reverse_apply.hpp
@@ -18,8 +18,8 @@ BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
BOOST_HANA_CONSTEXPR_LAMBDA auto reverse_apply =
[](auto&& f, auto&& ...x) -> decltype(auto) {
return detail::variadic::reverse_apply_unrolled(
- static_cast<decltype(f)&&>(f),
- static_cast<decltype(x)&&>(x)...
+ static_cast<decltype(f)>(f),
+ static_cast<decltype(x)>(x)...
);
};
}} BOOST_HANA_NAMESPACE_END
diff --git a/boost/hana/experimental/printable.hpp b/boost/hana/experimental/printable.hpp
index f41d3fd906..637ebe6927 100644
--- a/boost/hana/experimental/printable.hpp
+++ b/boost/hana/experimental/printable.hpp
@@ -98,7 +98,7 @@ BOOST_HANA_NAMESPACE_BEGIN namespace experimental {
};
namespace print_detail {
- std::string strip_type_junk(std::string const& str) {
+ inline std::string strip_type_junk(std::string const& str) {
return std::regex_replace(str, std::regex("(?:struct )?([a-z_]+::)*([a-z_]*)_t<((?:struct )?[a-z:<>_]*)>"), "$2<$3>");
}
}
diff --git a/boost/hana/functional/apply.hpp b/boost/hana/functional/apply.hpp
index 8a47a873e6..d705767e19 100644
--- a/boost/hana/functional/apply.hpp
+++ b/boost/hana/functional/apply.hpp
@@ -35,7 +35,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//! @include example/functional/apply.cpp
//!
//! [1]: http://en.cppreference.com/w/cpp/utility/functional/invoke
- //! [2]: http://en.cppreference.com/w/cpp/concept/Callable
+ //! [2]: http://en.cppreference.com/w/cpp/named_req/Callable
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto apply = [](auto&& f, auto&& ...x) -> decltype(auto) {
return forwarded(f)(forwarded(x)...);
diff --git a/boost/hana/functional/curry.hpp b/boost/hana/functional/curry.hpp
index 74ec09459a..762718c208 100644
--- a/boost/hana/functional/curry.hpp
+++ b/boost/hana/functional/curry.hpp
@@ -111,13 +111,13 @@ BOOST_HANA_NAMESPACE_BEGIN
template <std::size_t n>
constexpr make_curry_t<n> curry{};
- namespace curry_detail {
+ namespace curry_detail { namespace {
template <std::size_t n>
constexpr make_curry_t<n> curry_or_call{};
template <>
constexpr auto curry_or_call<0> = apply;
- }
+ }}
template <std::size_t n, typename F>
struct curry_t {
diff --git a/boost/hana/fwd/ap.hpp b/boost/hana/fwd/ap.hpp
index 6f7b147090..271a1631d1 100644
--- a/boost/hana/fwd/ap.hpp
+++ b/boost/hana/fwd/ap.hpp
@@ -29,11 +29,10 @@ BOOST_HANA_NAMESPACE_BEGIN
//! number of `x...` must match the arity of the functions in the `f`
//! structure. In other words, `ap(f, x1, ..., xN)` is equivalent to
//! @code
- //! ((f' <ap> x1) <ap> x2) ... <ap> xN
+ //! ((curry(f) ap x1) ap x2) ... ap xN
//! @endcode
- //! where `f'` is `f` but containing curried functions instead and
- //! `x <ap> y` is just `ap(x, y)` written in infix notation to emphasize
- //! the left associativity.
+ //! where `x ap y` is just `ap(x, y)` written in infix notation to
+ //! emphasize the left associativity.
//!
//!
//! Signature
diff --git a/boost/hana/fwd/concept/comparable.hpp b/boost/hana/fwd/concept/comparable.hpp
index 9624c87038..db1b45d947 100644
--- a/boost/hana/fwd/concept/comparable.hpp
+++ b/boost/hana/fwd/concept/comparable.hpp
@@ -151,7 +151,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//!
//! [1]: http://en.wikipedia.org/wiki/Equivalence_relation#Definition
//! [2]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf
- //! [3]: http://en.cppreference.com/w/cpp/concept/EqualityComparable
+ //! [3]: http://en.cppreference.com/w/cpp/named_req/EqualityComparable
//! [4]: http://en.wikipedia.org/wiki/Injective_function
template <typename T>
struct Comparable;
diff --git a/boost/hana/fwd/concept/constant.hpp b/boost/hana/fwd/concept/constant.hpp
index bab44a7cb2..4a4799ac6e 100644
--- a/boost/hana/fwd/concept/constant.hpp
+++ b/boost/hana/fwd/concept/constant.hpp
@@ -202,7 +202,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//! reasons as explained above, this common type is still provided.
//!
//!
- //! [1]: http://en.cppreference.com/w/cpp/concept/LiteralType
+ //! [1]: http://en.cppreference.com/w/cpp/named_req/LiteralType
template <typename C>
struct Constant;
BOOST_HANA_NAMESPACE_END
diff --git a/boost/hana/fwd/concept/metafunction.hpp b/boost/hana/fwd/concept/metafunction.hpp
index 72884911f3..a480c0b1d4 100644
--- a/boost/hana/fwd/concept/metafunction.hpp
+++ b/boost/hana/fwd/concept/metafunction.hpp
@@ -90,7 +90,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//! deep comparison. Hence, we adopt a conservative stance and avoid
//! providing comparison for `Metafunction`s.
//!
- //! [1]: http://en.cppreference.com/w/cpp/concept/FunctionObject
+ //! [1]: http://en.cppreference.com/w/cpp/named_req/FunctionObject
//! [2]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/metafunction-class.html
template <typename F>
struct Metafunction;
diff --git a/boost/hana/fwd/concept/orderable.hpp b/boost/hana/fwd/concept/orderable.hpp
index 7c4cf233db..e7730ee299 100644
--- a/boost/hana/fwd/concept/orderable.hpp
+++ b/boost/hana/fwd/concept/orderable.hpp
@@ -177,7 +177,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//!
//!
//! [1]: http://en.wikipedia.org/wiki/Total_order
- //! [2]: http://en.cppreference.com/w/cpp/concept/LessThanComparable
+ //! [2]: http://en.cppreference.com/w/cpp/named_req/LessThanComparable
//! [3]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf
//! [4]: http://en.wikipedia.org/wiki/Strict_weak_ordering
template <typename Ord>
diff --git a/boost/hana/pair.hpp b/boost/hana/pair.hpp
index 35ff857269..d88b8ad8d4 100644
--- a/boost/hana/pair.hpp
+++ b/boost/hana/pair.hpp
@@ -37,7 +37,11 @@ BOOST_HANA_NAMESPACE_BEGIN
//////////////////////////////////////////////////////////////////////////
//! @cond
template <typename First, typename Second>
+#ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
+ struct __declspec(empty_bases) pair : detail::operators::adl<pair<First, Second>>
+#else
struct pair : detail::operators::adl<pair<First, Second>>
+#endif
, private detail::ebo<detail::pix<0>, First>
, private detail::ebo<detail::pix<1>, Second>
{
diff --git a/boost/hana/string.hpp b/boost/hana/string.hpp
index a7b83dee86..aea19bd2ed 100644
--- a/boost/hana/string.hpp
+++ b/boost/hana/string.hpp
@@ -271,7 +271,7 @@ BOOST_HANA_NAMESPACE_BEGIN
template <char ...xs, typename N>
static constexpr auto apply(string<xs...> const& s, N const&) {
return helper<N::value>(s, std::make_index_sequence<
- N::value < sizeof...(xs) ? sizeof...(xs) - N::value : 0
+ (N::value < sizeof...(xs)) ? sizeof...(xs) - N::value : 0
>{});
}
diff --git a/boost/hana/tuple.hpp b/boost/hana/tuple.hpp
index ae3cba819d..a81ab9da69 100644
--- a/boost/hana/tuple.hpp
+++ b/boost/hana/tuple.hpp
@@ -75,7 +75,11 @@ BOOST_HANA_NAMESPACE_BEGIN
// tuple
//////////////////////////////////////////////////////////////////////////
template <>
+#ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
+ struct __declspec(empty_bases) tuple<> final
+#else
struct tuple<> final
+#endif
: detail::operators::adl<tuple<>>
, detail::iterable_operators<tuple<>>
{
@@ -84,7 +88,11 @@ BOOST_HANA_NAMESPACE_BEGIN
};
template <typename ...Xn>
+#ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
+ struct __declspec(empty_bases) tuple final
+#else
struct tuple final
+#endif
: detail::operators::adl<tuple<Xn...>>
, detail::iterable_operators<tuple<Xn...>>
{
@@ -256,7 +264,7 @@ BOOST_HANA_NAMESPACE_BEGIN
static constexpr auto apply(Xs&& xs, N const&) {
constexpr std::size_t len = decltype(hana::length(xs))::value;
return helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence<
- N::value < len ? len - N::value : 0
+ (N::value < len) ? len - N::value : 0
>{});
}
};
diff --git a/boost/hana/version.hpp b/boost/hana/version.hpp
index c3a5b3982d..af8daac64d 100644
--- a/boost/hana/version.hpp
+++ b/boost/hana/version.hpp
@@ -24,7 +24,7 @@ Distributed under the Boost Software License, Version 1.0.
//! @ingroup group-config
//! Macro expanding to the minor version of the library, i.e. the `y` in `x.y.z`.
-#define BOOST_HANA_MINOR_VERSION 5
+#define BOOST_HANA_MINOR_VERSION 6
//! @ingroup group-config
//! Macro expanding to the patch level of the library, i.e. the `z` in `x.y.z`.
diff --git a/boost/heap/detail/stable_heap.hpp b/boost/heap/detail/stable_heap.hpp
index b207ed39af..a16632ff1e 100644
--- a/boost/heap/detail/stable_heap.hpp
+++ b/boost/heap/detail/stable_heap.hpp
@@ -173,19 +173,21 @@ struct heap_base:
heap_base(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value):
#ifndef BOOST_MSVC
Cmp(std::move(static_cast<Cmp&>(rhs))),
-#else
- cmp_(std::move(rhs.cmp_)),
#endif
size_holder_type(std::move(static_cast<size_holder_type&>(rhs)))
+#ifdef BOOST_MSVC
+ , cmp_(std::move(rhs.cmp_))
+#endif
{}
heap_base(heap_base const & rhs):
#ifndef BOOST_MSVC
Cmp(static_cast<Cmp const &>(rhs)),
-#else
- cmp_(rhs.value_comp()),
#endif
size_holder_type(static_cast<size_holder_type const &>(rhs))
+#ifdef BOOST_MSVC
+ , cmp_(rhs.value_comp())
+#endif
{}
heap_base & operator=(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_assignable<Cmp>::value)
diff --git a/boost/heap/policies.hpp b/boost/heap/policies.hpp
index 6bdba2bff2..6a251a9faa 100644
--- a/boost/heap/policies.hpp
+++ b/boost/heap/policies.hpp
@@ -9,8 +9,12 @@
#ifndef BOOST_HEAP_POLICIES_HPP
#define BOOST_HEAP_POLICIES_HPP
-#include <boost/parameter.hpp>
#include <boost/concept_check.hpp>
+#include <boost/parameter/name.hpp>
+#include <boost/parameter/template_keyword.hpp>
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/parameter/binding.hpp>
+#include <boost/parameter/parameters.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_void.hpp>
diff --git a/boost/histogram.hpp b/boost/histogram.hpp
index 97efb469eb..44cb4b1036 100644
--- a/boost/histogram.hpp
+++ b/boost/histogram.hpp
@@ -12,14 +12,20 @@
Includes all standard headers of the Boost.histogram library.
Extra headers not automatically included are:
- - boost/histogram/accumulators/ostream.hpp
- - boost/histogram/axis/ostream.hpp
- - boost/histogram/ostream.hpp
- - boost/histogram/serialization.hpp
+ - [boost/histogram/ostream.hpp][1]
+ - [boost/histogram/axis/ostream.hpp][2]
+ - [boost/histogram/accumulators/ostream.hpp][3]
+ - [boost/histogram/serialization.hpp][4]
+
+ [1]: histogram/reference.html#header.boost.histogram.ostream_hpp
+ [2]: histogram/reference.html#header.boost.histogram.axis.ostream_hpp
+ [3]: histogram/reference.html#header.boost.histogram.accumulators.ostream_hpp
+ [4]: histogram/reference.html#header.boost.histogram.serialization_hpp
*/
#include <boost/histogram/accumulators/mean.hpp>
#include <boost/histogram/accumulators/sum.hpp>
+#include <boost/histogram/accumulators/thread_safe.hpp>
#include <boost/histogram/accumulators/weighted_mean.hpp>
#include <boost/histogram/accumulators/weighted_sum.hpp>
#include <boost/histogram/algorithm/project.hpp>
diff --git a/boost/histogram/accumulators.hpp b/boost/histogram/accumulators.hpp
new file mode 100644
index 0000000000..b515c1de5c
--- /dev/null
+++ b/boost/histogram/accumulators.hpp
@@ -0,0 +1,16 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_ACCUMULATORS_HPP
+#define BOOST_HISTOGRAM_ACCUMULATORS_HPP
+
+#include <boost/histogram/accumulators/mean.hpp>
+#include <boost/histogram/accumulators/sum.hpp>
+#include <boost/histogram/accumulators/thread_safe.hpp>
+#include <boost/histogram/accumulators/weighted_mean.hpp>
+#include <boost/histogram/accumulators/weighted_sum.hpp>
+
+#endif
diff --git a/boost/histogram/accumulators/ostream.hpp b/boost/histogram/accumulators/ostream.hpp
index b88c133ae3..76e102a562 100644
--- a/boost/histogram/accumulators/ostream.hpp
+++ b/boost/histogram/accumulators/ostream.hpp
@@ -10,39 +10,58 @@
#include <boost/histogram/fwd.hpp>
#include <iosfwd>
+/**
+ \file boost/histogram/accumulators/ostream.hpp
+ Simple streaming operators for the builtin accumulator types.
+
+ The text representation is not guaranteed to be stable between versions of
+ Boost.Histogram. This header is only included by
+ [boost/histogram/ostream.hpp](histogram/reference.html#header.boost.histogram.ostream_hpp).
+ To you use your own, include your own implementation instead of this header and do not
+ include
+ [boost/histogram/ostream.hpp](histogram/reference.html#header.boost.histogram.ostream_hpp).
+ */
+
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
namespace boost {
namespace histogram {
namespace accumulators {
-template <typename CharT, typename Traits, typename W>
+template <class CharT, class Traits, class W>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
const sum<W>& x) {
os << "sum(" << x.large() << " + " << x.small() << ")";
return os;
}
-template <typename CharT, typename Traits, typename W>
+template <class CharT, class Traits, class W>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
const weighted_sum<W>& x) {
os << "weighted_sum(" << x.value() << ", " << x.variance() << ")";
return os;
}
-template <typename CharT, typename Traits, typename W>
+template <class CharT, class Traits, class W>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
const mean<W>& x) {
os << "mean(" << x.count() << ", " << x.value() << ", " << x.variance() << ")";
return os;
}
-template <typename CharT, typename Traits, typename W>
+template <class CharT, class Traits, class W>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
const weighted_mean<W>& x) {
os << "weighted_mean(" << x.sum_of_weights() << ", " << x.value() << ", "
<< x.variance() << ")";
return os;
}
+
+template <class CharT, class Traits, class T>
+std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
+ const thread_safe<T>& x) {
+ os << x.load();
+ return os;
+}
} // namespace accumulators
} // namespace histogram
} // namespace boost
diff --git a/boost/histogram/accumulators/thread_safe.hpp b/boost/histogram/accumulators/thread_safe.hpp
new file mode 100644
index 0000000000..699bd4b1e4
--- /dev/null
+++ b/boost/histogram/accumulators/thread_safe.hpp
@@ -0,0 +1,57 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_ACCUMULATORS_THREAD_SAFE_HPP
+#define BOOST_HISTOGRAM_ACCUMULATORS_THREAD_SAFE_HPP
+
+#include <atomic>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+
+namespace boost {
+namespace histogram {
+namespace accumulators {
+
+/** Thread-safe adaptor for builtin integral and floating point numbers.
+
+ This adaptor uses std::atomic to make concurrent increments and additions safe for the
+ stored value.
+
+ On common computing platforms, the adapted integer has the same size and
+ alignment as underlying type. The atomicity is implemented with a special CPU
+ instruction. On exotic platforms the size of the adapted number may be larger and/or the
+ type may have different alignment, which means it cannot be tightly packed into arrays.
+
+ @tparam T type to adapt, must be supported by std::atomic.
+ */
+template <class T>
+class thread_safe : public std::atomic<T> {
+public:
+ using super_t = std::atomic<T>;
+
+ thread_safe() noexcept : super_t(static_cast<T>(0)) {}
+ // non-atomic copy and assign is allowed, because storage is locked in this case
+ thread_safe(const thread_safe& o) noexcept : super_t(o.load()) {}
+ thread_safe& operator=(const thread_safe& o) noexcept {
+ super_t::store(o.load());
+ return *this;
+ }
+
+ thread_safe(T arg) : super_t(arg) {}
+ thread_safe& operator=(T arg) {
+ super_t::store(arg);
+ return *this;
+ }
+
+ void operator+=(T arg) { super_t::fetch_add(arg, std::memory_order_relaxed); }
+ void operator++() { operator+=(static_cast<T>(1)); }
+};
+
+} // namespace accumulators
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/algorithm/project.hpp b/boost/histogram/algorithm/project.hpp
index be69fe87b6..6c0495c8d0 100644
--- a/boost/histogram/algorithm/project.hpp
+++ b/boost/histogram/algorithm/project.hpp
@@ -8,16 +8,20 @@
#define BOOST_HISTOGRAM_ALGORITHM_PROJECT_HPP
#include <algorithm>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/axis/variant.hpp>
+#include <boost/histogram/detail/detect.hpp>
+#include <boost/histogram/detail/make_default.hpp>
+#include <boost/histogram/detail/static_if.hpp>
#include <boost/histogram/histogram.hpp>
#include <boost/histogram/indexed.hpp>
#include <boost/histogram/unsafe_access.hpp>
-#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/set.hpp>
+#include <boost/mp11/utility.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
#include <type_traits>
+#include <vector>
namespace boost {
namespace histogram {
@@ -41,8 +45,7 @@ auto project(const histogram<A, S>& h, std::integral_constant<unsigned, N>, Ns..
return std::make_tuple(std::get<N>(old_axes), std::get<Ns::value>(old_axes)...);
},
[&](const auto& old_axes) {
- return detail::remove_cvref_t<decltype(old_axes)>(
- {old_axes[N], old_axes[Ns::value]...});
+ return std::decay_t<decltype(old_axes)>({old_axes[N], old_axes[Ns::value]...});
},
old_axes);
@@ -50,7 +53,7 @@ auto project(const histogram<A, S>& h, std::integral_constant<unsigned, N>, Ns..
using A2 = decltype(axes);
auto result = histogram<A2, S>(std::move(axes), detail::make_default(old_storage));
auto idx = detail::make_stack_buffer<int>(unsafe_access::axes(result));
- for (auto x : indexed(h, coverage::all)) {
+ for (auto&& x : indexed(h, coverage::all)) {
auto i = idx.begin();
mp11::mp_for_each<LN>([&i, &x](auto J) { *i++ = x.index(J); });
result.at(idx) += *x;
@@ -66,23 +69,24 @@ auto project(const histogram<A, S>& h, std::integral_constant<unsigned, N>, Ns..
*/
template <class A, class S, class Iterable, class = detail::requires_iterable<Iterable>>
auto project(const histogram<A, S>& h, const Iterable& c) {
- static_assert(detail::is_sequence_of_any_axis<A>::value,
- "this version of project requires histogram with non-static axes");
-
+ using namespace boost::mp11;
const auto& old_axes = unsafe_access::axes(h);
- auto axes = detail::make_default(old_axes);
+
+ // axes is always std::vector<...>, even if A is tuple
+ auto axes = detail::make_empty_dynamic_axes(old_axes);
axes.reserve(c.size());
auto seen = detail::make_stack_buffer<bool>(old_axes, false);
for (auto d : c) {
if (seen[d]) BOOST_THROW_EXCEPTION(std::invalid_argument("indices must be unique"));
seen[d] = true;
- axes.emplace_back(old_axes[d]);
+ axes.emplace_back(detail::axis_get(old_axes, d));
}
const auto& old_storage = unsafe_access::storage(h);
- auto result = histogram<A, S>(std::move(axes), detail::make_default(old_storage));
+ auto result =
+ histogram<decltype(axes), S>(std::move(axes), detail::make_default(old_storage));
auto idx = detail::make_stack_buffer<int>(unsafe_access::axes(result));
- for (auto x : indexed(h, coverage::all)) {
+ for (auto&& x : indexed(h, coverage::all)) {
auto i = idx.begin();
for (auto d : c) *i++ = x.index(d);
result.at(idx) += *x;
diff --git a/boost/histogram/algorithm/reduce.hpp b/boost/histogram/algorithm/reduce.hpp
index 12db033785..ba71cb7246 100644
--- a/boost/histogram/algorithm/reduce.hpp
+++ b/boost/histogram/algorithm/reduce.hpp
@@ -1,4 +1,4 @@
-// Copyright 2018 Hans Dembinski
+// Copyright 2018-2019 Hans Dembinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
@@ -8,43 +8,42 @@
#define BOOST_HISTOGRAM_ALGORITHM_REDUCE_HPP
#include <boost/assert.hpp>
+#include <boost/histogram/axis/traits.hpp>
#include <boost/histogram/detail/axes.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/cat.hpp>
+#include <boost/histogram/detail/make_default.hpp>
+#include <boost/histogram/detail/static_if.hpp>
+#include <boost/histogram/detail/type_name.hpp>
#include <boost/histogram/fwd.hpp>
#include <boost/histogram/indexed.hpp>
#include <boost/histogram/unsafe_access.hpp>
#include <boost/throw_exception.hpp>
#include <cmath>
-#include <limits>
+#include <initializer_list>
#include <stdexcept>
-#include <type_traits>
namespace boost {
namespace histogram {
-namespace algorithm {
-
-/**
- Option type returned by the helper functions shrink_and_rebin(), shrink(), rebin().
- */
+namespace detail {
struct reduce_option {
-#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
unsigned iaxis = 0;
- double lower, upper;
+ bool indices_set = false;
+ axis::index_type begin = 0, end = 0;
+ bool values_set = false;
+ double lower = 0.0, upper = 0.0;
unsigned merge = 0;
+};
+} // namespace detail
- reduce_option() noexcept = default;
+namespace algorithm {
- reduce_option(unsigned i, double l, double u, unsigned m)
- : iaxis(i), lower(l), upper(u), merge(m) {
- if (lower == upper)
- BOOST_THROW_EXCEPTION(std::invalid_argument("lower != upper required"));
- if (merge == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("merge > 0 required"));
- }
-#endif
-};
+using reduce_option = detail::reduce_option;
/**
- Shrink and rebin option.
+ Shrink and rebin option to be used in reduce().
+
+ To shrink and rebin in one command. Equivalent to passing both the shrink() and the
+ rebin() option for the same axis to reduce.
@param iaxis which axis to operate on.
@param lower lowest bound that should be kept.
@@ -52,90 +51,162 @@ struct reduce_option {
whole interval is removed.
@param merge how many adjacent bins to merge into one.
*/
-inline auto shrink_and_rebin(unsigned iaxis, double lower, double upper, unsigned merge) {
- return reduce_option{iaxis, lower, upper, merge};
+inline reduce_option shrink_and_rebin(unsigned iaxis, double lower, double upper,
+ unsigned merge) {
+ if (lower == upper)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("lower != upper required"));
+ if (merge == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("merge > 0 required"));
+ return {iaxis, false, 0, 0, true, lower, upper, merge};
+}
+
+/**
+ Slice and rebin option to be used in reduce().
+
+ To slice and rebin in one command. Equivalent to passing both the slice() and the
+ rebin() option for the same axis to reduce.
+
+ @param iaxis which axis to operate on.
+ @param begin first index that should be kept.
+ @param end one past the last index that should be kept.
+ @param merge how many adjacent bins to merge into one.
+ */
+inline reduce_option slice_and_rebin(unsigned iaxis, axis::index_type begin,
+ axis::index_type end, unsigned merge) {
+ if (!(begin < end))
+ BOOST_THROW_EXCEPTION(std::invalid_argument("begin < end required"));
+ if (merge == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("merge > 0 required"));
+ return {iaxis, true, begin, end, false, 0.0, 0.0, merge};
}
/**
- Shrink option.
+ Shrink option to be used in reduce().
@param iaxis which axis to operate on.
@param lower lowest bound that should be kept.
@param upper highest bound that should be kept. If upper is inside bin interval, the
whole interval is removed.
*/
-inline auto shrink(unsigned iaxis, double lower, double upper) {
- return reduce_option{iaxis, lower, upper, 1};
+inline reduce_option shrink(unsigned iaxis, double lower, double upper) {
+ return shrink_and_rebin(iaxis, lower, upper, 1);
+}
+
+/**
+ Slice option to be used in reduce().
+
+ @param iaxis which axis to operate on.
+ @param begin first index that should be kept.
+ @param end one past the last index that should be kept.
+ */
+inline reduce_option slice(unsigned iaxis, axis::index_type begin, axis::index_type end) {
+ return slice_and_rebin(iaxis, begin, end, 1);
}
/**
- Rebin option.
+ Rebin option to be used in reduce().
@param iaxis which axis to operate on.
@param merge how many adjacent bins to merge into one.
*/
-inline auto rebin(unsigned iaxis, unsigned merge) {
- return reduce_option{iaxis, std::numeric_limits<double>::quiet_NaN(),
- std::numeric_limits<double>::quiet_NaN(), merge};
+inline reduce_option rebin(unsigned iaxis, unsigned merge) {
+ if (merge == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("merge > 0 required"));
+ return reduce_option{iaxis, false, 0, 0, false, 0.0, 0.0, merge};
}
/**
- Convenience overload for single axis.
+ Shrink and rebin option to be used in reduce() (onvenience overload for
+ single axis).
@param lower lowest bound that should be kept.
@param upper highest bound that should be kept. If upper is inside bin interval, the
whole interval is removed.
@param merge how many adjacent bins to merge into one.
*/
-inline auto shrink_and_rebin(double lower, double upper, unsigned merge) {
+inline reduce_option shrink_and_rebin(double lower, double upper, unsigned merge) {
return shrink_and_rebin(0, lower, upper, merge);
}
/**
- Convenience overload for single axis.
+ Slice and rebin option to be used in reduce() (convenience for 1D histograms).
+
+ @param begin first index that should be kept.
+ @param end one past the last index that should be kept.
+ @param merge how many adjacent bins to merge into one.
+*/
+inline reduce_option slice_and_rebin(axis::index_type begin, axis::index_type end,
+ unsigned merge) {
+ return slice_and_rebin(0, begin, end, merge);
+}
+
+/**
+ Shrink option to be used in reduce() (convenience for 1D histograms).
@param lower lowest bound that should be kept.
@param upper highest bound that should be kept. If upper is inside bin interval, the
whole interval is removed.
*/
-inline auto shrink(double lower, double upper) { return shrink(0, lower, upper); }
+inline reduce_option shrink(double lower, double upper) {
+ return shrink(0, lower, upper);
+}
+
+/**
+ Slice option to be used in reduce() (convenience for 1D histograms).
+
+ @param begin first index that should be kept.
+ @param end one past the last index that should be kept.
+*/
+inline reduce_option slice(axis::index_type begin, axis::index_type end) {
+ return slice(0, begin, end);
+}
/**
- Convenience overload for single axis.
+ Rebin option to be used in reduce() (convenience for 1D histograms).
@param merge how many adjacent bins to merge into one.
*/
-inline auto rebin(unsigned merge) { return rebin(0, merge); }
+inline reduce_option rebin(unsigned merge) { return rebin(0, merge); }
/**
- Shrink and/or rebin axes of a histogram.
+ Shrink, slice, and/or rebin axes of a histogram.
Returns the reduced copy of the histogram.
+ Shrinking only works with axes that accept double values. Some axis types do not support
+ the reduce operation, for example, the builtin category axis, which is not ordered.
+ Custom axis types must implement a special constructor (see concepts) to be reducible.
+
@param hist original histogram.
- @param options iterable sequence of reduce_options, generated by shrink_and_rebin(),
- shrink(), and rebin().
+ @param options iterable sequence of reduce options, generated by shrink_and_rebin(),
+ slice_and_rebin(), shrink(), slice(), and rebin().
*/
-#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
template <class Histogram, class Iterable, class = detail::requires_iterable<Iterable>>
-#else
-template <class Histogram, class Iterable>
-#endif
decltype(auto) reduce(const Histogram& hist, const Iterable& options) {
const auto& old_axes = unsafe_access::axes(hist);
- struct option_item : reduce_option {
- int begin, end;
- };
-
- auto opts = detail::make_stack_buffer<option_item>(old_axes);
- for (const auto& o : options) {
- auto& oi = opts[o.iaxis];
- if (oi.merge > 0) // did we already set the option for this axis?
- BOOST_THROW_EXCEPTION(std::invalid_argument("indices must be unique"));
- oi.lower = o.lower;
- oi.upper = o.upper;
- oi.merge = o.merge;
+ auto opts = detail::make_stack_buffer<reduce_option>(old_axes);
+ for (const reduce_option& o_in : options) {
+ BOOST_ASSERT(o_in.merge > 0);
+ if (o_in.iaxis >= hist.rank())
+ BOOST_THROW_EXCEPTION(std::invalid_argument("invalid axis index"));
+ reduce_option& o_out = opts[o_in.iaxis];
+ if (o_out.merge > 0) {
+ // some option was already set for this axis, see if we can merge requests
+ if (o_in.merge > 1 && o_out.merge > 1)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("conflicting merge requests"));
+ if ((o_in.indices_set || o_in.values_set) &&
+ (o_out.indices_set || o_out.values_set))
+ BOOST_THROW_EXCEPTION(
+ std::invalid_argument("conflicting slice or shrink requests"));
+ }
+ if (o_in.values_set) {
+ o_out.values_set = true;
+ o_out.lower = o_in.lower;
+ o_out.upper = o_in.upper;
+ } else if (o_in.indices_set) {
+ o_out.indices_set = true;
+ o_out.begin = o_in.begin;
+ o_out.end = o_in.end;
+ }
+ o_out.merge = std::max(o_in.merge, o_out.merge);
}
// make new axes container with default-constructed axis instances
@@ -144,33 +215,52 @@ decltype(auto) reduce(const Histogram& hist, const Iterable& options) {
[](auto&, const auto&) {},
[](auto& axes, const auto& old_axes) {
axes.reserve(old_axes.size());
- for (const auto& a : old_axes) axes.emplace_back(detail::make_default(a));
+ detail::for_each_axis(old_axes, [&axes](const auto& a) {
+ axes.emplace_back(detail::make_default(a));
+ });
},
axes, old_axes);
// override default-constructed axis instances with modified instances
unsigned iaxis = 0;
hist.for_each_axis([&](const auto& a) {
- using T = detail::remove_cvref_t<decltype(a)>;
-
+ using A = std::decay_t<decltype(a)>;
auto& o = opts[iaxis];
- o.begin = 0;
- o.end = a.size();
if (o.merge > 0) { // option is set?
- if (o.lower < o.upper) {
- while (o.begin != o.end && a.value(o.begin) < o.lower) ++o.begin;
- while (o.end != o.begin && a.value(o.end - 1) >= o.upper) --o.end;
- } else if (o.lower > o.upper) {
- // for inverted axis::regular
- while (o.begin != o.end && a.value(o.begin) > o.lower) ++o.begin;
- while (o.end != o.begin && a.value(o.end - 1) <= o.upper) --o.end;
- }
- o.end -= (o.end - o.begin) % o.merge;
- auto a2 = T(a, o.begin, o.end, o.merge);
- axis::get<T>(detail::axis_get(axes, iaxis)) = a2;
+ detail::static_if_c<axis::traits::is_reducible<A>::value>(
+ [&o](auto&& aout, const auto& ain) {
+ using A = std::decay_t<decltype(ain)>;
+ if (o.indices_set) {
+ o.begin = std::max(0, o.begin);
+ o.end = std::min(o.end, ain.size());
+ } else {
+ o.begin = 0;
+ o.end = ain.size();
+ if (o.values_set) {
+ if (o.lower < o.upper) {
+ while (o.begin != o.end && ain.value(o.begin) < o.lower) ++o.begin;
+ while (o.end != o.begin && ain.value(o.end - 1) >= o.upper) --o.end;
+ } else if (o.lower > o.upper) {
+ // for inverted axis::regular
+ while (o.begin != o.end && ain.value(o.begin) > o.lower) ++o.begin;
+ while (o.end != o.begin && ain.value(o.end - 1) <= o.upper) --o.end;
+ }
+ }
+ }
+ o.end -= (o.end - o.begin) % o.merge;
+ aout = A(ain, o.begin, o.end, o.merge);
+ },
+ [](auto&&, const auto& ain) {
+ using A = std::decay_t<decltype(ain)>;
+ BOOST_THROW_EXCEPTION(std::invalid_argument(
+ detail::cat(detail::type_name<A>(), " is not reducible")));
+ },
+ axis::get<A>(detail::axis_get(axes, iaxis)), a);
} else {
o.merge = 1;
- axis::get<T>(detail::axis_get(axes, iaxis)) = a;
+ o.begin = 0;
+ o.end = a.size();
+ axis::get<A>(detail::axis_get(axes, iaxis)) = a;
}
++iaxis;
});
@@ -179,7 +269,7 @@ decltype(auto) reduce(const Histogram& hist, const Iterable& options) {
auto result = Histogram(std::move(axes), std::move(storage));
auto idx = detail::make_stack_buffer<int>(unsafe_access::axes(result));
- for (auto x : indexed(hist, coverage::all)) {
+ for (auto&& x : indexed(hist, coverage::all)) {
auto i = idx.begin();
auto o = opts.begin();
for (auto j : x.indices()) {
@@ -201,16 +291,21 @@ decltype(auto) reduce(const Histogram& hist, const Iterable& options) {
}
/**
- Shrink and/or rebin axes of a histogram.
+ Shrink, slice, and/or rebin axes of a histogram.
+
+ Returns the reduced copy of the histogram.
- Returns the modified copy.
+ Shrinking only works with axes that accept double values. Some axis types do not support
+ the reduce operation, for example, the builtin category axis, which is not ordered.
+ Custom axis types must implement a special constructor (see concepts) to be reducible.
@param hist original histogram.
@param opt reduce option generated by shrink_and_rebin(), shrink(), and rebin().
- @param opts more reduce_options.
+ @param opts more reduce options.
*/
template <class Histogram, class... Ts>
-decltype(auto) reduce(const Histogram& hist, const reduce_option& opt, Ts&&... opts) {
+decltype(auto) reduce(const Histogram& hist, const reduce_option& opt,
+ const Ts&... opts) {
// this must be in one line, because any of the ts could be a temporary
return reduce(hist, std::initializer_list<reduce_option>{opt, opts...});
}
diff --git a/boost/histogram/algorithm/sum.hpp b/boost/histogram/algorithm/sum.hpp
index 63316adef3..5ff437dd6f 100644
--- a/boost/histogram/algorithm/sum.hpp
+++ b/boost/histogram/algorithm/sum.hpp
@@ -30,7 +30,7 @@ auto sum(const histogram<A, S>& h) {
using T = typename histogram<A, S>::value_type;
using Sum = mp11::mp_if<std::is_arithmetic<T>, accumulators::sum<double>, T>;
Sum sum;
- for (auto x : h) sum += x;
+ for (auto&& x : h) sum += x;
using R = mp11::mp_if<std::is_arithmetic<T>, double, T>;
return static_cast<R>(sum);
}
diff --git a/boost/histogram/axis/category.hpp b/boost/histogram/axis/category.hpp
index 03a3b842ea..309aae0d6b 100644
--- a/boost/histogram/axis/category.hpp
+++ b/boost/histogram/axis/category.hpp
@@ -11,10 +11,13 @@
#include <boost/histogram/axis/iterator.hpp>
#include <boost/histogram/axis/option.hpp>
#include <boost/histogram/detail/compressed_pair.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/detect.hpp>
+#include <boost/histogram/detail/relaxed_equal.hpp>
+#include <boost/histogram/detail/replace_default.hpp>
#include <boost/histogram/fwd.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
+#include <string>
#include <type_traits>
#include <utility>
#include <vector>
@@ -56,6 +59,22 @@ class category : public iterator_mixin<category<Value, MetaData, Options, Alloca
public:
explicit category(allocator_type alloc = {}) : vec_meta_(vector_type(alloc)) {}
+ category(const category&) = default;
+ category& operator=(const category&) = default;
+ category(category&& o) noexcept : vec_meta_(std::move(o.vec_meta_)) {
+ // std::string explicitly guarantees nothrow only in C++17
+ static_assert(std::is_same<metadata_type, std::string>::value ||
+ std::is_nothrow_move_constructible<metadata_type>::value,
+ "");
+ }
+ category& operator=(category&& o) noexcept {
+ // std::string explicitly guarantees nothrow only in C++17
+ static_assert(std::is_same<metadata_type, std::string>::value ||
+ std::is_nothrow_move_assignable<metadata_type>::value,
+ "");
+ vec_meta_ = std::move(o.vec_meta_);
+ return *this;
+ }
/** Construct from iterator range of unique values.
*
@@ -92,14 +111,6 @@ public:
allocator_type alloc = {})
: category(list.begin(), list.end(), std::move(meta), std::move(alloc)) {}
- /// Constructor used by algorithm::reduce to shrink and rebin.
- category(const category& src, index_type begin, index_type end, unsigned merge)
- : category(src.vec_meta_.first().begin() + begin,
- src.vec_meta_.first().begin() + end, src.metadata()) {
- if (merge > 1)
- BOOST_THROW_EXCEPTION(std::invalid_argument("cannot merge bins for category axis"));
- }
-
/// Return index for value argument.
index_type index(const value_type& x) const noexcept {
const auto beg = vec_meta_.first().begin();
diff --git a/boost/histogram/axis/integer.hpp b/boost/histogram/axis/integer.hpp
index 6e55d83354..8768b0fbfa 100644
--- a/boost/histogram/axis/integer.hpp
+++ b/boost/histogram/axis/integer.hpp
@@ -10,12 +10,17 @@
#include <boost/histogram/axis/iterator.hpp>
#include <boost/histogram/axis/option.hpp>
#include <boost/histogram/detail/compressed_pair.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/convert_integer.hpp>
+#include <boost/histogram/detail/limits.hpp>
+#include <boost/histogram/detail/relaxed_equal.hpp>
+#include <boost/histogram/detail/replace_default.hpp>
+#include <boost/histogram/detail/static_if.hpp>
#include <boost/histogram/fwd.hpp>
#include <boost/throw_exception.hpp>
#include <cmath>
#include <limits>
#include <stdexcept>
+#include <string>
#include <type_traits>
#include <utility>
@@ -52,6 +57,23 @@ class integer : public iterator_mixin<integer<Value, MetaData, Options>> {
public:
constexpr integer() = default;
+ integer(const integer&) = default;
+ integer& operator=(const integer&) = default;
+ integer(integer&& o) noexcept : size_meta_(std::move(o.size_meta_)), min_(o.min_) {
+ // std::string explicitly guarantees nothrow only in C++17
+ static_assert(std::is_same<metadata_type, std::string>::value ||
+ std::is_nothrow_move_constructible<metadata_type>::value,
+ "");
+ }
+ integer& operator=(integer&& o) noexcept {
+ // std::string explicitly guarantees nothrow only in C++17
+ static_assert(std::is_same<metadata_type, std::string>::value ||
+ std::is_nothrow_move_assignable<metadata_type>::value,
+ "");
+ size_meta_ = std::move(o.size_meta_);
+ min_ = o.min_;
+ return *this;
+ }
/** Construct over semi-open integer interval [start, stop).
*
diff --git a/boost/histogram/axis/iterator.hpp b/boost/histogram/axis/iterator.hpp
index 29b8ee0091..8b8c15e392 100644
--- a/boost/histogram/axis/iterator.hpp
+++ b/boost/histogram/axis/iterator.hpp
@@ -8,34 +8,25 @@
#define BOOST_HISTOGRAM_AXIS_ITERATOR_HPP
#include <boost/histogram/axis/interval_view.hpp>
-#include <boost/histogram/detail/meta.hpp>
-#include <boost/iterator/iterator_adaptor.hpp>
-#include <boost/iterator/reverse_iterator.hpp>
+#include <boost/histogram/detail/iterator_adaptor.hpp>
+#include <iterator>
namespace boost {
namespace histogram {
namespace axis {
-template <typename Axis>
-class iterator
- : public boost::iterator_adaptor<iterator<Axis>, int,
- decltype(std::declval<const Axis&>().bin(0)),
- std::random_access_iterator_tag,
- decltype(std::declval<const Axis&>().bin(0)), int> {
+template <class Axis>
+class iterator : public detail::iterator_adaptor<iterator<Axis>, int,
+ decltype(std::declval<Axis>().bin(0))> {
public:
- explicit iterator(const Axis& axis, int idx)
- : iterator::iterator_adaptor_(idx), axis_(axis) {}
+ /// Make iterator from axis and index.
+ iterator(const Axis& axis, int idx) : iterator::iterator_adaptor_(idx), axis_(axis) {}
-protected:
- bool equal(const iterator& other) const noexcept {
- return &axis_ == &other.axis_ && this->base() == other.base();
- }
-
- decltype(auto) dereference() const { return axis_.bin(this->base()); }
+ /// Return current bin object.
+ decltype(auto) operator*() const { return axis_.bin(this->base()); }
private:
const Axis& axis_;
- friend class boost::iterator_core_access;
};
/// Uses CRTP to inject iterator logic into Derived.
@@ -43,7 +34,7 @@ template <typename Derived>
class iterator_mixin {
public:
using const_iterator = iterator<Derived>;
- using const_reverse_iterator = boost::reverse_iterator<const_iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
/// Bin iterator to beginning of the axis (read-only).
const_iterator begin() const noexcept {
@@ -58,12 +49,12 @@ public:
/// Reverse bin iterator to the last entry of the axis (read-only).
const_reverse_iterator rbegin() const noexcept {
- return boost::make_reverse_iterator(end());
+ return std::make_reverse_iterator(end());
}
/// Reverse bin iterator to the end (read-only).
const_reverse_iterator rend() const noexcept {
- return boost::make_reverse_iterator(begin());
+ return std::make_reverse_iterator(begin());
}
};
diff --git a/boost/histogram/axis/ostream.hpp b/boost/histogram/axis/ostream.hpp
index 282e7496c3..5a7295ade2 100644
--- a/boost/histogram/axis/ostream.hpp
+++ b/boost/histogram/axis/ostream.hpp
@@ -10,10 +10,10 @@
#define BOOST_HISTOGRAM_AXIS_OSTREAM_HPP
#include <boost/assert.hpp>
-#include <boost/core/typeinfo.hpp>
#include <boost/histogram/axis/regular.hpp>
#include <boost/histogram/detail/cat.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/static_if.hpp>
+#include <boost/histogram/detail/type_name.hpp>
#include <boost/histogram/fwd.hpp>
#include <boost/throw_exception.hpp>
#include <iomanip>
@@ -21,6 +21,18 @@
#include <stdexcept>
#include <type_traits>
+/**
+ \file boost/histogram/axis/ostream.hpp
+ Simple streaming operators for the builtin axis types.
+
+ The text representation is not guaranteed to be stable between versions of
+ Boost.Histogram. This header is only included by
+ [boost/histogram/ostream.hpp](histogram/reference.html#header.boost.histogram.ostream_hpp).
+ To you use your own, include your own implementation instead of this header and do not
+ include
+ [boost/histogram/ostream.hpp](histogram/reference.html#header.boost.histogram.ostream_hpp).
+ */
+
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
namespace boost {
@@ -40,10 +52,7 @@ void stream_metadata(OStream& os, const T& t) {
oss << t;
if (!oss.str().empty()) { os << ", metadata=" << std::quoted(oss.str()); }
},
- [&os](const auto&) {
- os << ", metadata=" << boost::core::demangled_name(BOOST_CORE_TYPEID(T));
- },
- t);
+ [&os](const auto&) { os << ", metadata=" << detail::type_name<T>(); }, t);
}
template <class OStream>
@@ -170,13 +179,12 @@ std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
const variant<Us...>& v) {
visit(
[&os](const auto& x) {
- using A = detail::remove_cvref_t<decltype(x)>;
+ using A = std::decay_t<decltype(x)>;
detail::static_if<detail::is_streamable<A>>(
[&os](const auto& x) { os << x; },
[](const auto&) {
BOOST_THROW_EXCEPTION(std::runtime_error(
- detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(A)),
- " is not streamable")));
+ detail::cat(detail::type_name<A>(), " is not streamable")));
},
x);
},
diff --git a/boost/histogram/axis/polymorphic_bin.hpp b/boost/histogram/axis/polymorphic_bin.hpp
index 1b70938e4c..773fcf1cdc 100644
--- a/boost/histogram/axis/polymorphic_bin.hpp
+++ b/boost/histogram/axis/polymorphic_bin.hpp
@@ -7,7 +7,7 @@
#ifndef BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
#define BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/detect.hpp>
#include <type_traits>
namespace boost {
@@ -15,20 +15,21 @@ namespace histogram {
namespace axis {
/**
- Holds the bin data of a axis::variant.
+ Holds the bin data of an axis::variant.
- The interface is a superset of the `value_bin_view` and `interval_bin_view`
- classes. The methods value() and lower() return the same number. For a value bin,
- upper() and lower() and center() return the same number, width() returns zero.
+ The interface is a superset of the axis::interval_view
+ class. In addition, the object is implicitly convertible to the value type,
+ returning the equivalent of a call to lower(). For discrete axes, lower() ==
+ upper(), and width() returns zero.
- This is not a view like interval_bin_view or value_bin_view for two reasons.
+ This is not a view like axis::interval_view for two reasons.
- Sequential calls to lower() and upper() would have to each loop through
the variant types. This is likely to be slower than filling all the data in
one loop.
- polymorphic_bin may be created from a temporary instance of axis::variant,
like in the call histogram::axis(0). Storing a reference to the axis would
result in a dangling reference. Rather than specialing the code to handle
- this, it seems easier to just use a value instead of a view here.
+ this, it seems easier to just use a value instead of a view.
*/
template <typename RealType>
class polymorphic_bin {
diff --git a/boost/histogram/axis/regular.hpp b/boost/histogram/axis/regular.hpp
index 6f6b2605a0..a7b9828ec0 100644
--- a/boost/histogram/axis/regular.hpp
+++ b/boost/histogram/axis/regular.hpp
@@ -12,18 +12,54 @@
#include <boost/histogram/axis/iterator.hpp>
#include <boost/histogram/axis/option.hpp>
#include <boost/histogram/detail/compressed_pair.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/convert_integer.hpp>
+#include <boost/histogram/detail/relaxed_equal.hpp>
+#include <boost/histogram/detail/replace_default.hpp>
#include <boost/histogram/fwd.hpp>
#include <boost/mp11/utility.hpp>
#include <boost/throw_exception.hpp>
#include <cmath>
#include <limits>
#include <stdexcept>
+#include <string>
#include <type_traits>
#include <utility>
namespace boost {
namespace histogram {
+namespace detail {
+
+template <class T>
+using get_scale_type_helper = typename T::value_type;
+
+template <class T>
+using get_scale_type = mp11::mp_eval_or<T, detail::get_scale_type_helper, T>;
+
+struct one_unit {};
+
+template <class T>
+T operator*(T&& t, const one_unit&) {
+ return std::forward<T>(t);
+}
+
+template <class T>
+T operator/(T&& t, const one_unit&) {
+ return std::forward<T>(t);
+}
+
+template <class T>
+using get_unit_type_helper = typename T::unit_type;
+
+template <class T>
+using get_unit_type = mp11::mp_eval_or<one_unit, detail::get_unit_type_helper, T>;
+
+template <class T, class R = get_scale_type<T>>
+R get_scale(const T& t) {
+ return t / get_unit_type<T>();
+}
+
+} // namespace detail
+
namespace axis {
namespace transform {
@@ -140,6 +176,31 @@ class regular : public iterator_mixin<regular<Value, Transform, MetaData, Option
public:
constexpr regular() = default;
+ regular(const regular&) = default;
+ regular& operator=(const regular&) = default;
+ regular(regular&& o) noexcept
+ : transform_type(std::move(o))
+ , size_meta_(std::move(o.size_meta_))
+ , min_(o.min_)
+ , delta_(o.delta_) {
+ static_assert(std::is_nothrow_move_constructible<transform_type>::value, "");
+ // std::string explicitly guarantees nothrow only in C++17
+ static_assert(std::is_same<metadata_type, std::string>::value ||
+ std::is_nothrow_move_constructible<metadata_type>::value,
+ "");
+ }
+ regular& operator=(regular&& o) noexcept {
+ static_assert(std::is_nothrow_move_assignable<transform_type>::value, "");
+ // std::string explicitly guarantees nothrow only in C++17
+ static_assert(std::is_same<metadata_type, std::string>::value ||
+ std::is_nothrow_move_assignable<metadata_type>::value,
+ "");
+ transform_type::operator=(std::move(o));
+ size_meta_ = std::move(o.size_meta_);
+ min_ = o.min_;
+ delta_ = o.delta_;
+ return *this;
+ }
/** Construct n bins over real transformed range [start, stop).
*
@@ -347,10 +408,15 @@ regular(Tr, unsigned, T, T, M)->regular<detail::convert_integer<T, double>, Tr,
#endif
+/// Regular axis with circular option already set.
template <class Value = double, class MetaData = use_default, class Options = use_default>
+#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
using circular = regular<Value, transform::id, MetaData,
decltype(detail::replace_default<Options, option::overflow_t>{} |
option::circular)>;
+#else
+class circular;
+#endif
} // namespace axis
} // namespace histogram
diff --git a/boost/histogram/axis/traits.hpp b/boost/histogram/axis/traits.hpp
index 48e3dbf135..d907d6dd54 100644
--- a/boost/histogram/axis/traits.hpp
+++ b/boost/histogram/axis/traits.hpp
@@ -7,12 +7,19 @@
#ifndef BOOST_HISTOGRAM_AXIS_TRAITS_HPP
#define BOOST_HISTOGRAM_AXIS_TRAITS_HPP
-#include <boost/core/typeinfo.hpp>
#include <boost/histogram/axis/option.hpp>
+#include <boost/histogram/detail/args_type.hpp>
#include <boost/histogram/detail/cat.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/detect.hpp>
+#include <boost/histogram/detail/static_if.hpp>
+#include <boost/histogram/detail/try_cast.hpp>
+#include <boost/histogram/detail/type_name.hpp>
#include <boost/histogram/fwd.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
#include <boost/throw_exception.hpp>
+#include <boost/variant2/variant.hpp>
#include <stdexcept>
#include <utility>
@@ -23,45 +30,68 @@ namespace detail {
template <class T>
using static_options_impl = axis::option::bitset<T::options()>;
-template <class FIntArg, class FDoubleArg, class T>
-decltype(auto) value_method_switch(FIntArg&& iarg, FDoubleArg&& darg, const T& t) {
- return static_if<has_method_value<T>>(
- [](FIntArg&& iarg, FDoubleArg&& darg, const auto& t) {
- using A = remove_cvref_t<decltype(t)>;
- return static_if<std::is_same<arg_type<decltype(&A::value), 0>, int>>(
- std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
- },
- [](FIntArg&&, FDoubleArg&&, const auto& t) -> double {
- using A = remove_cvref_t<decltype(t)>;
- BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
- boost::core::demangled_name(BOOST_CORE_TYPEID(A)), " has no value method")));
-#ifndef _MSC_VER // msvc warns about unreachable return
- return double{};
-#endif
- },
- std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
+template <class I, class D, class A>
+double value_method_switch_impl1(std::false_type, I&&, D&&, const A&) {
+ // comma trick to make all compilers happy; some would complain about
+ // unreachable code after the throw, others about a missing return
+ return BOOST_THROW_EXCEPTION(
+ std::runtime_error(cat(type_name<A>(), " has no value method"))),
+ double{};
}
-template <class R1, class R2, class FIntArg, class FDoubleArg, class T>
-R2 value_method_switch_with_return_type(FIntArg&& iarg, FDoubleArg&& darg, const T& t) {
- return static_if<has_method_value_with_convertible_return_type<T, R1>>(
- [](FIntArg&& iarg, FDoubleArg&& darg, const auto& t) -> R2 {
- using A = remove_cvref_t<decltype(t)>;
- return static_if<std::is_same<arg_type<decltype(&A::value), 0>, int>>(
- std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
- },
- [](FIntArg&&, FDoubleArg&&, const auto&) -> R2 {
- BOOST_THROW_EXCEPTION(std::runtime_error(
- detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(T)),
- " has no value method or return type is not convertible to ",
- boost::core::demangled_name(BOOST_CORE_TYPEID(R1)))));
-#ifndef _MSC_VER // msvc warns about unreachable return
- // conjure a value out of thin air to satisfy syntactic requirement
- return *reinterpret_cast<R2*>(0);
-#endif
- },
- std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
+template <class I, class D, class A>
+decltype(auto) value_method_switch_impl1(std::true_type, I&& i, D&& d, const A& a) {
+ using T = arg_type<decltype(&A::value)>;
+ return static_if<std::is_same<T, axis::index_type>>(std::forward<I>(i),
+ std::forward<D>(d), a);
+}
+
+template <class I, class D, class A>
+decltype(auto) value_method_switch(I&& i, D&& d, const A& a) {
+ return value_method_switch_impl1(has_method_value<A>{}, std::forward<I>(i),
+ std::forward<D>(d), a);
}
+
+static axis::null_type null_value;
+
+struct variant_access {
+ template <class T, class T0, class Variant>
+ static auto get_if_impl(mp11::mp_list<T, T0>, Variant* v) noexcept {
+ return variant2::get_if<T>(&(v->impl));
+ }
+
+ template <class T, class T0, class Variant>
+ static auto get_if_impl(mp11::mp_list<T, T0*>, Variant* v) noexcept {
+ auto tp = variant2::get_if<mp11::mp_if<std::is_const<T0>, const T*, T*>>(&(v->impl));
+ return tp ? *tp : nullptr;
+ }
+
+ template <class T, class Variant>
+ static auto get_if(Variant* v) noexcept {
+ using T0 = mp11::mp_first<std::decay_t<Variant>>;
+ return get_if_impl(mp11::mp_list<T, T0>{}, v);
+ }
+
+ template <class T0, class Visitor, class Variant>
+ static decltype(auto) visit_impl(mp11::mp_identity<T0>, Visitor&& vis, Variant&& v) {
+ return variant2::visit(std::forward<Visitor>(vis), v.impl);
+ }
+
+ template <class T0, class Visitor, class Variant>
+ static decltype(auto) visit_impl(mp11::mp_identity<T0*>, Visitor&& vis, Variant&& v) {
+ return variant2::visit(
+ [&vis](auto&& x) -> decltype(auto) { return std::forward<Visitor>(vis)(*x); },
+ v.impl);
+ }
+
+ template <class Visitor, class Variant>
+ static decltype(auto) visit(Visitor&& vis, Variant&& v) {
+ using T0 = mp11::mp_first<std::decay_t<Variant>>;
+ return visit_impl(mp11::mp_identity<T0>{}, std::forward<Visitor>(vis),
+ std::forward<Variant>(v));
+ }
+};
+
} // namespace detail
namespace axis {
@@ -77,32 +107,35 @@ namespace traits {
*/
template <class Axis>
decltype(auto) metadata(Axis&& axis) noexcept {
- return detail::static_if<
- detail::has_method_metadata<const detail::remove_cvref_t<Axis>>>(
+ return detail::static_if<detail::has_method_metadata<std::decay_t<Axis>>>(
[](auto&& a) -> decltype(auto) { return a.metadata(); },
- [](auto &&) -> detail::copy_qualifiers<Axis, null_type> {
- static null_type m;
- return m;
+ [](auto &&) -> mp11::mp_if<std::is_const<std::remove_reference_t<Axis>>,
+ axis::null_type const&, axis::null_type&> {
+ return detail::null_value;
},
std::forward<Axis>(axis));
}
-/** Generates static axis option type for axis type.
+/** Get static axis options for axis type.
- WARNING: Doxygen does not render the synopsis correctly. This is a templated using
- directive, which accepts axis type and returns boost::histogram::axis::option::bitset.
+ Doxygen does not render this well. This is a meta-function, it accepts an axis
+ type and represents its boost::histogram::axis::option::bitset.
- If Axis::options() is valid and constexpr, return the corresponding option type.
- Otherwise, return boost::histogram::axis::option::growth_t, if the axis has a method
- `update`, else return boost::histogram::axis::option::none_t.
+ If Axis::options() is valid and constexpr, static_options is the corresponding
+ option type. Otherwise, it is boost::histogram::axis::option::growth_t, if the
+ axis has a method `update`, else boost::histogram::axis::option::none_t.
@tparam Axis axis type
*/
template <class Axis>
-using static_options = detail::mp_eval_or<
- mp11::mp_if<detail::has_method_update<detail::remove_cvref_t<Axis>>, option::growth_t,
- option::none_t>,
- detail::static_options_impl, detail::remove_cvref_t<Axis>>;
+#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
+using static_options =
+ mp11::mp_eval_or<mp11::mp_if<detail::has_method_update<std::decay_t<Axis>>,
+ option::growth_t, option::none_t>,
+ detail::static_options_impl, std::decay_t<Axis>>;
+#else
+struct static_options;
+#endif
/** Returns axis options as unsigned integer.
@@ -113,7 +146,7 @@ using static_options = detail::mp_eval_or<
*/
template <class Axis>
constexpr unsigned options(const Axis& axis) noexcept {
- // cannot reuse static_options here, because this should also work for axis::variant
+ // cannot reuse static_options here, must also work for axis::variant
return detail::static_if<detail::has_method_options<Axis>>(
[](const auto& a) { return a.options(); },
[](const auto&) { return static_options<Axis>::value; }, axis);
@@ -143,7 +176,7 @@ constexpr index_type extent(const Axis& axis) noexcept {
template <class Axis>
decltype(auto) value(const Axis& axis, real_index_type index) {
return detail::value_method_switch(
- [index](const auto& a) { return a.value(static_cast<int>(index)); },
+ [index](const auto& a) { return a.value(static_cast<index_type>(index)); },
[index](const auto& a) { return a.value(index); }, axis);
}
@@ -159,11 +192,8 @@ decltype(auto) value(const Axis& axis, real_index_type index) {
*/
template <class Result, class Axis>
Result value_as(const Axis& axis, real_index_type index) {
- return detail::value_method_switch_with_return_type<Result, Result>(
- [index](const auto& a) {
- return static_cast<Result>(a.value(static_cast<int>(index)));
- },
- [index](const auto& a) { return static_cast<Result>(a.value(index)); }, axis);
+ return detail::try_cast<Result, std::runtime_error>(
+ value(axis, index)); // avoid conversion warning
}
/** Returns axis index for value.
@@ -173,31 +203,16 @@ Result value_as(const Axis& axis, real_index_type index) {
@param axis any axis instance
@param value argument to be passed to `index` method
*/
-template <class Axis, class U>
-auto index(const Axis& axis, const U& value) {
- using V = detail::arg_type<decltype(&Axis::index)>;
- return detail::static_if<std::is_convertible<U, V>>(
- [&value](const auto& axis) {
- using A = detail::remove_cvref_t<decltype(axis)>;
- using V2 = detail::arg_type<decltype(&A::index)>;
- return axis.index(static_cast<V2>(value));
- },
- [](const Axis&) -> index_type {
- BOOST_THROW_EXCEPTION(std::invalid_argument(
- detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(Axis)),
- ": cannot convert argument of type ",
- boost::core::demangled_name(BOOST_CORE_TYPEID(U)), " to ",
- boost::core::demangled_name(BOOST_CORE_TYPEID(V)))));
-#ifndef _MSC_VER // msvc warns about unreachable return
- return index_type{};
-#endif
- },
- axis);
+template <class Axis, class U,
+ class _V = std::decay_t<detail::arg_type<decltype(&Axis::index)>>>
+axis::index_type index(const Axis& axis,
+ const U& value) noexcept(std::is_convertible<U, _V>::value) {
+ return axis.index(detail::try_cast<_V, std::invalid_argument>(value));
}
-/// @copydoc index(const Axis&, const U& value)
+// specialization for variant
template <class... Ts, class U>
-auto index(const variant<Ts...>& axis, const U& value) {
+axis::index_type index(const variant<Ts...>& axis, const U& value) {
return axis.index(value);
}
@@ -212,33 +227,21 @@ auto index(const variant<Ts...>& axis, const U& value) {
@param axis any axis instance
@param value argument to be passed to `update` or `index` method
*/
-template <class Axis, class U>
-std::pair<int, int> update(Axis& axis, const U& value) {
- using V = detail::arg_type<decltype(&Axis::index)>;
- return detail::static_if<std::is_convertible<U, V>>(
+template <class Axis, class U,
+ class _V = std::decay_t<detail::arg_type<decltype(&Axis::index)>>>
+std::pair<index_type, index_type> update(Axis& axis, const U& value) noexcept(
+ std::is_convertible<U, _V>::value) {
+ return detail::static_if_c<static_options<Axis>::test(option::growth)>(
[&value](auto& a) {
- using A = detail::remove_cvref_t<decltype(a)>;
- return detail::static_if_c<static_options<A>::test(option::growth)>(
- [&value](auto& a) { return a.update(value); },
- [&value](auto& a) { return std::make_pair(a.index(value), 0); }, a);
+ return a.update(detail::try_cast<_V, std::invalid_argument>(value));
},
- [](Axis&) -> std::pair<index_type, index_type> {
- BOOST_THROW_EXCEPTION(std::invalid_argument(
- detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(Axis)),
- ": cannot convert argument of type ",
- boost::core::demangled_name(BOOST_CORE_TYPEID(U)), " to ",
- boost::core::demangled_name(BOOST_CORE_TYPEID(V)))));
-#ifndef _MSC_VER // msvc warns about unreachable return
- return std::make_pair(index_type{}, index_type{});
-#endif
- },
- axis);
+ [&value](auto& a) { return std::make_pair(index(a, value), index_type{0}); }, axis);
}
-/// @copydoc update(Axis& axis, const U& value)
+// specialization for variant
template <class... Ts, class U>
-auto update(variant<Ts...>& axis, const U& value) {
- return axis.update(value);
+std::pair<index_type, index_type> update(variant<Ts...>& axis, const U& value) {
+ return visit([&value](auto& a) { return a.update(value); }, axis);
}
/** Returns bin width at axis index.
@@ -267,14 +270,31 @@ decltype(auto) width(const Axis& axis, index_type index) {
*/
template <class Result, class Axis>
Result width_as(const Axis& axis, index_type index) {
- return detail::value_method_switch_with_return_type<Result, Result>(
+ return detail::value_method_switch(
[](const auto&) { return Result{}; },
[index](const auto& a) {
- return static_cast<Result>(a.value(index + 1) - a.value(index));
+ return detail::try_cast<Result, std::runtime_error>(a.value(index + 1) -
+ a.value(index));
},
axis);
}
+/** Meta-function to detect whether an axis is reducible.
+
+ Doxygen does not render this well. This is a meta-function, it accepts an axis
+ type and represents std::true_type or std::false_type, depending on whether the axis can
+ be reduced with boost::histogram::algorithm::reduce().
+
+ @tparam Axis axis type.
+ */
+template <class Axis>
+#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
+using is_reducible = std::is_constructible<Axis, const Axis&, axis::index_type,
+ axis::index_type, unsigned>;
+#else
+struct is_reducible;
+#endif
+
} // namespace traits
} // namespace axis
} // namespace histogram
diff --git a/boost/histogram/axis/variable.hpp b/boost/histogram/axis/variable.hpp
index d3d6b855cf..10641c96ee 100644
--- a/boost/histogram/axis/variable.hpp
+++ b/boost/histogram/axis/variable.hpp
@@ -13,13 +13,18 @@
#include <boost/histogram/axis/iterator.hpp>
#include <boost/histogram/axis/option.hpp>
#include <boost/histogram/detail/compressed_pair.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/convert_integer.hpp>
+#include <boost/histogram/detail/detect.hpp>
+#include <boost/histogram/detail/limits.hpp>
+#include <boost/histogram/detail/relaxed_equal.hpp>
+#include <boost/histogram/detail/replace_default.hpp>
#include <boost/histogram/fwd.hpp>
#include <boost/throw_exception.hpp>
#include <cmath>
#include <limits>
#include <memory>
#include <stdexcept>
+#include <string>
#include <type_traits>
#include <utility>
#include <vector>
@@ -52,7 +57,23 @@ class variable : public iterator_mixin<variable<Value, MetaData, Options, Alloca
using vec_type = std::vector<Value, allocator_type>;
public:
- explicit variable(allocator_type alloc = {}) : vec_meta_(std::move(alloc)) {}
+ explicit variable(allocator_type alloc = {}) : vec_meta_(vec_type{alloc}) {}
+ variable(const variable&) = default;
+ variable& operator=(const variable&) = default;
+ variable(variable&& o) noexcept : vec_meta_(std::move(o.vec_meta_)) {
+ // std::string explicitly guarantees nothrow only in C++17
+ static_assert(std::is_same<metadata_type, std::string>::value ||
+ std::is_nothrow_move_constructible<metadata_type>::value,
+ "");
+ }
+ variable& operator=(variable&& o) noexcept {
+ // std::string explicitly guarantees nothrow only in C++17
+ static_assert(std::is_same<metadata_type, std::string>::value ||
+ std::is_nothrow_move_assignable<metadata_type>::value,
+ "");
+ vec_meta_ = std::move(o.vec_meta_);
+ return *this;
+ }
/** Construct from iterator range of bin edges.
*
@@ -215,22 +236,19 @@ variable(std::initializer_list<U>, const char*)->variable<T>;
template <class U, class M, class T = detail::convert_integer<U, double>>
variable(std::initializer_list<U>, M)->variable<T, M>;
-template <
- class Iterable,
- class T = detail::convert_integer<
- detail::remove_cvref_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
+template <class Iterable,
+ class T = detail::convert_integer<
+ std::decay_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
variable(Iterable)->variable<T>;
-template <
- class Iterable,
- class T = detail::convert_integer<
- detail::remove_cvref_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
+template <class Iterable,
+ class T = detail::convert_integer<
+ std::decay_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
variable(Iterable, const char*)->variable<T>;
-template <
- class Iterable, class M,
- class T = detail::convert_integer<
- detail::remove_cvref_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
+template <class Iterable, class M,
+ class T = detail::convert_integer<
+ std::decay_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
variable(Iterable, M)->variable<T, M>;
#endif
diff --git a/boost/histogram/axis/variant.hpp b/boost/histogram/axis/variant.hpp
index 55ba85ab34..aa13fefbb3 100644
--- a/boost/histogram/axis/variant.hpp
+++ b/boost/histogram/axis/variant.hpp
@@ -7,24 +7,21 @@
#ifndef BOOST_HISTOGRAM_AXIS_VARIANT_HPP
#define BOOST_HISTOGRAM_AXIS_VARIANT_HPP
-#include <boost/core/typeinfo.hpp>
#include <boost/histogram/axis/iterator.hpp>
#include <boost/histogram/axis/polymorphic_bin.hpp>
#include <boost/histogram/axis/traits.hpp>
#include <boost/histogram/detail/cat.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/relaxed_equal.hpp>
+#include <boost/histogram/detail/static_if.hpp>
+#include <boost/histogram/detail/type_name.hpp>
#include <boost/histogram/fwd.hpp>
-#include <boost/mp11/bind.hpp>
#include <boost/mp11/function.hpp>
#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
#include <boost/throw_exception.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/get.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant.hpp>
+#include <boost/variant2/variant.hpp>
#include <ostream>
#include <stdexcept>
-#include <tuple>
#include <type_traits>
#include <utility>
@@ -32,27 +29,20 @@ namespace boost {
namespace histogram {
namespace axis {
-template <class T, class... Us>
-T* get_if(variant<Us...>* v);
-
-template <class T, class... Us>
-const T* get_if(const variant<Us...>* v);
-
/// Polymorphic axis type
template <class... Ts>
class variant : public iterator_mixin<variant<Ts...>> {
- using impl_type = boost::variant<Ts...>;
- using raw_types = mp11::mp_transform<detail::remove_cvref_t, impl_type>;
+ using impl_type = boost::variant2::variant<Ts...>;
template <class T>
- using is_bounded_type = mp11::mp_contains<raw_types, detail::remove_cvref_t<T>>;
+ using is_bounded_type = mp11::mp_contains<variant, std::decay_t<T>>;
template <typename T>
using requires_bounded_type = std::enable_if_t<is_bounded_type<T>::value>;
// maybe metadata_type or const metadata_type, if bounded type is const
using metadata_type = std::remove_reference_t<decltype(
- traits::metadata(std::declval<mp11::mp_first<impl_type>>()))>;
+ traits::metadata(std::declval<std::remove_pointer_t<mp11::mp_first<variant>>>()))>;
public:
// cannot import ctors with using directive, it breaks gcc and msvc
@@ -62,10 +52,10 @@ public:
variant(variant&&) = default;
variant& operator=(variant&&) = default;
- template <typename T, typename = requires_bounded_type<T>>
+ template <class T, class = requires_bounded_type<T>>
variant(T&& t) : impl(std::forward<T>(t)) {}
- template <typename T, typename = requires_bounded_type<T>>
+ template <class T, class = requires_bounded_type<T>>
variant& operator=(T&& t) {
impl = std::forward<T>(t);
return *this;
@@ -80,14 +70,13 @@ public:
variant& operator=(const variant<Us...>& u) {
visit(
[this](const auto& u) {
- using U = detail::remove_cvref_t<decltype(u)>;
+ using U = std::decay_t<decltype(u)>;
detail::static_if<is_bounded_type<U>>(
[this](const auto& u) { this->operator=(u); },
[](const auto&) {
BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
- boost::core::demangled_name(BOOST_CORE_TYPEID(U)),
- " is not convertible to a bounded type of ",
- boost::core::demangled_name(BOOST_CORE_TYPEID(variant)))));
+ detail::type_name<U>(), " is not convertible to a bounded type of ",
+ detail::type_name<variant>())));
},
u);
},
@@ -97,12 +86,12 @@ public:
/// Return size of axis.
index_type size() const {
- return visit([](const auto& x) { return x.size(); }, *this);
+ return visit([](const auto& a) { return a.size(); }, *this);
}
/// Return options of axis or option::none_t if axis has no options.
unsigned options() const {
- return visit([](const auto& x) { return axis::traits::options(x); }, *this);
+ return visit([](const auto& a) { return axis::traits::options(a); }, *this);
}
/// Return reference to const metadata or instance of null_type if axis has no
@@ -114,13 +103,12 @@ public:
return detail::static_if<std::is_same<M, const metadata_type&>>(
[](const auto& a) -> const metadata_type& { return traits::metadata(a); },
[](const auto&) -> const metadata_type& {
- BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
- "cannot return metadata of type ",
- boost::core::demangled_name(BOOST_CORE_TYPEID(M)),
- " through axis::variant interface which uses type ",
- boost::core::demangled_name(BOOST_CORE_TYPEID(metadata_type)),
- "; use boost::histogram::axis::get to obtain a reference "
- "of this axis type")));
+ BOOST_THROW_EXCEPTION(std::runtime_error(
+ detail::cat("cannot return metadata of type ", detail::type_name<M>(),
+ " through axis::variant interface which uses type ",
+ detail::type_name<metadata_type>(),
+ "; use boost::histogram::axis::get to obtain a reference "
+ "of this axis type")));
},
a);
},
@@ -131,166 +119,184 @@ public:
/// metadata.
metadata_type& metadata() {
return visit(
- [](auto&& a) -> metadata_type& {
+ [](auto& a) -> metadata_type& {
using M = decltype(traits::metadata(a));
return detail::static_if<std::is_same<M, metadata_type&>>(
[](auto& a) -> metadata_type& { return traits::metadata(a); },
[](auto&) -> metadata_type& {
- BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
- "cannot return metadata of type ",
- boost::core::demangled_name(BOOST_CORE_TYPEID(M)),
- " through axis::variant interface which uses type ",
- boost::core::demangled_name(BOOST_CORE_TYPEID(metadata_type)),
- "; use boost::histogram::axis::get to obtain a reference "
- "of this axis type")));
+ BOOST_THROW_EXCEPTION(std::runtime_error(
+ detail::cat("cannot return metadata of type ", detail::type_name<M>(),
+ " through axis::variant interface which uses type ",
+ detail::type_name<metadata_type>(),
+ "; use boost::histogram::axis::get to obtain a reference "
+ "of this axis type")));
},
a);
},
*this);
}
- /// Return index for value argument.
- /// Throws std::invalid_argument if axis has incompatible call signature.
+ /** Return index for value argument.
+
+ Throws std::invalid_argument if axis has incompatible call signature.
+ */
template <class U>
index_type index(const U& u) const {
return visit([&u](const auto& a) { return traits::index(a, u); }, *this);
}
- /// Return value for index argument.
- /// Only works for axes with value method that returns something convertible
- /// to double and will throw a runtime_error otherwise, see
- /// axis::traits::value().
+ /** Return value for index argument.
+
+ Only works for axes with value method that returns something convertible
+ to double and will throw a runtime_error otherwise, see
+ axis::traits::value().
+ */
double value(real_index_type idx) const {
return visit([idx](const auto& a) { return traits::value_as<double>(a, idx); },
*this);
}
- /// Return bin for index argument.
- /// Only works for axes with value method that returns something convertible
- /// to double and will throw a runtime_error otherwise, see
- /// axis::traits::value().
+ /** Return bin for index argument.
+
+ Only works for axes with value method that returns something convertible
+ to double and will throw a runtime_error otherwise, see
+ axis::traits::value().
+ */
auto bin(index_type idx) const {
return visit(
[idx](const auto& a) {
- return detail::value_method_switch_with_return_type<double,
- polymorphic_bin<double>>(
+ return detail::value_method_switch(
[idx](const auto& a) { // axis is discrete
- const auto x = a.value(idx);
+ const double x = traits::value_as<double>(a, idx);
return polymorphic_bin<double>(x, x);
},
[idx](const auto& a) { // axis is continuous
- return polymorphic_bin<double>(a.value(idx), a.value(idx + 1));
+ const double x1 = traits::value_as<double>(a, idx);
+ const double x2 = traits::value_as<double>(a, idx + 1);
+ return polymorphic_bin<double>(x1, x2);
},
a);
},
*this);
}
+ /** Compare two variants.
+
+ Return true if the variants point to the same concrete axis type and the types compare
+ equal. Otherwise return false.
+ */
template <class... Us>
bool operator==(const variant<Us...>& u) const {
return visit([&u](const auto& x) { return u == x; }, *this);
}
+ /** Compare variant with a concrete axis type.
+
+ Return true if the variant point to the same concrete axis type and the types compare
+ equal. Otherwise return false.
+ */
template <class T>
bool operator==(const T& t) const {
- // boost::variant::operator==(T) implemented only to fail, cannot use it
- auto tp = get_if<T>(this);
- return tp && detail::relaxed_equal(*tp, t);
+ return detail::static_if_c<(mp11::mp_contains<impl_type, T>::value ||
+ mp11::mp_contains<impl_type, T*>::value ||
+ mp11::mp_contains<impl_type, const T*>::value)>(
+ [&](const auto& t) {
+ using U = std::decay_t<decltype(t)>;
+ const U* tp = detail::variant_access::template get_if<U>(this);
+ return tp && detail::relaxed_equal(*tp, t);
+ },
+ [&](const auto&) { return false; }, t);
}
+ /// The negation of operator==.
template <class T>
bool operator!=(const T& t) const {
return !operator==(t);
}
- template <class Archive>
- void serialize(Archive& ar, unsigned);
-
- template <class Visitor, class Variant>
- friend auto visit(Visitor&&, Variant &&)
- -> detail::visitor_return_type<Visitor, Variant>;
-
- template <class T, class... Us>
- friend T& get(variant<Us...>& v);
-
- template <class T, class... Us>
- friend const T& get(const variant<Us...>& v);
+private:
+ impl_type impl;
- template <class T, class... Us>
- friend T&& get(variant<Us...>&& v);
+ friend struct detail::variant_access;
+ friend struct boost::histogram::unsafe_access;
+};
- template <class T, class... Us>
- friend T* get_if(variant<Us...>* v);
+// specialization for empty argument list, useful for meta-programming
+template <>
+class variant<> {};
- template <class T, class... Us>
- friend const T* get_if(const variant<Us...>* v);
+/// Apply visitor to variant (reference).
+template <class Visitor, class... Us>
+decltype(auto) visit(Visitor&& vis, variant<Us...>& var) {
+ return detail::variant_access::visit(vis, var);
+}
-private:
- boost::variant<Ts...> impl;
-};
+/// Apply visitor to variant (movable reference).
+template <class Visitor, class... Us>
+decltype(auto) visit(Visitor&& vis, variant<Us...>&& var) {
+ return detail::variant_access::visit(vis, std::move(var));
+}
-/// Apply visitor to variant.
-template <class Visitor, class Variant>
-auto visit(Visitor&& vis, Variant&& var)
- -> detail::visitor_return_type<Visitor, Variant> {
- return boost::apply_visitor(std::forward<Visitor>(vis), var.impl);
+/// Apply visitor to variant (const reference).
+template <class Visitor, class... Us>
+decltype(auto) visit(Visitor&& vis, const variant<Us...>& var) {
+ return detail::variant_access::visit(vis, var);
}
-/// Return lvalue reference to T, throws unspecified exception if type does not
-/// match.
+/// Returns pointer to T in variant or null pointer if type does not match.
template <class T, class... Us>
-T& get(variant<Us...>& v) {
- return boost::get<T>(v.impl);
+T* get_if(variant<Us...>* v) {
+ return detail::variant_access::template get_if<T>(v);
}
-/// Return rvalue reference to T, throws unspecified exception if type does not
-/// match.
+/// Returns pointer to const T in variant or null pointer if type does not match.
template <class T, class... Us>
-T&& get(variant<Us...>&& v) {
- return boost::get<T>(std::move(v.impl));
+const T* get_if(const variant<Us...>* v) {
+ return detail::variant_access::template get_if<T>(v);
}
-/// Return const reference to T, throws unspecified exception if type does not
-/// match.
+/// Return reference to T, throws std::runtime_error if type does not match.
template <class T, class... Us>
-const T& get(const variant<Us...>& v) {
- return boost::get<T>(v.impl);
+decltype(auto) get(variant<Us...>& v) {
+ auto tp = get_if<T>(&v);
+ if (!tp) BOOST_THROW_EXCEPTION(std::runtime_error("T is not the held type"));
+ return *tp;
}
-/// Returns pointer to T in variant or null pointer if type does not match.
+/// Return movable reference to T, throws unspecified exception if type does not match.
template <class T, class... Us>
-T* get_if(variant<Us...>* v) {
- return boost::relaxed_get<T>(&(v->impl));
+decltype(auto) get(variant<Us...>&& v) {
+ auto tp = get_if<T>(&v);
+ if (!tp) BOOST_THROW_EXCEPTION(std::runtime_error("T is not the held type"));
+ return std::move(*tp);
}
-/// Returns pointer to const T in variant or null pointer if type does not
-/// match.
+/// Return const reference to T, throws unspecified exception if type does not match.
template <class T, class... Us>
-const T* get_if(const variant<Us...>* v) {
- return boost::relaxed_get<T>(&(v->impl));
+decltype(auto) get(const variant<Us...>& v) {
+ auto tp = get_if<T>(&v);
+ if (!tp) BOOST_THROW_EXCEPTION(std::runtime_error("T is not the held type"));
+ return *tp;
}
-#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
// pass-through version of get for generic programming
template <class T, class U>
decltype(auto) get(U&& u) {
- return static_cast<detail::copy_qualifiers<U, T>>(u);
+ return std::forward<U>(u);
}
// pass-through version of get_if for generic programming
template <class T, class U>
T* get_if(U* u) {
- return std::is_same<T, detail::remove_cvref_t<U>>::value ? reinterpret_cast<T*>(u)
- : nullptr;
+ return std::is_same<T, std::decay_t<U>>::value ? reinterpret_cast<T*>(u) : nullptr;
}
// pass-through version of get_if for generic programming
template <class T, class U>
const T* get_if(const U* u) {
- return std::is_same<T, detail::remove_cvref_t<U>>::value ? reinterpret_cast<const T*>(u)
- : nullptr;
+ return std::is_same<T, std::decay_t<U>>::value ? reinterpret_cast<const T*>(u)
+ : nullptr;
}
-#endif
} // namespace axis
} // namespace histogram
diff --git a/boost/histogram/detail/args_type.hpp b/boost/histogram/detail/args_type.hpp
new file mode 100644
index 0000000000..a6c442d550
--- /dev/null
+++ b/boost/histogram/detail/args_type.hpp
@@ -0,0 +1,38 @@
+// Copyright 2015-2018 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_ARGS_TYPE_HPP
+#define BOOST_HISTOGRAM_DETAIL_ARGS_TYPE_HPP
+
+#include <boost/config/workaround.hpp>
+#if BOOST_WORKAROUND(BOOST_GCC, >= 60000)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnoexcept-type"
+#endif
+#include <boost/callable_traits/args.hpp>
+#if BOOST_WORKAROUND(BOOST_GCC, >= 60000)
+#pragma GCC diagnostic pop
+#endif
+#include <boost/mp11/list.hpp> // mp_pop_front
+#include <tuple>
+#include <type_traits> // is_member_function_pointer
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <class T, class Args = boost::callable_traits::args_t<T>>
+using args_type = std::conditional_t<std::is_member_function_pointer<T>::value,
+ mp11::mp_pop_front<Args>, Args>;
+
+template <class T, std::size_t N = 0>
+using arg_type = std::tuple_element_t<N, args_type<T>>;
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/attribute.hpp b/boost/histogram/detail/attribute.hpp
index 1fbfc43e9e..436b11498b 100644
--- a/boost/histogram/detail/attribute.hpp
+++ b/boost/histogram/detail/attribute.hpp
@@ -8,9 +8,9 @@
#define BOOST_HISTOGRAM_DETAIL_ATTRIBUTE_HPP
#if __cplusplus >= 201703L
-#define BOOST_HISTOGRAM_DETAIL_NODISCARD [[nodiscard]]
+#define BOOST_HISTOGRAM_NODISCARD [[nodiscard]]
#else
-#define BOOST_HISTOGRAM_DETAIL_NODISCARD
+#define BOOST_HISTOGRAM_NODISCARD
#endif
#endif
diff --git a/boost/histogram/detail/axes.hpp b/boost/histogram/detail/axes.hpp
index 7af45c3e45..1372936d4e 100644
--- a/boost/histogram/detail/axes.hpp
+++ b/boost/histogram/detail/axes.hpp
@@ -7,23 +7,49 @@
#ifndef BOOST_HISTOGRAM_DETAIL_AXES_HPP
#define BOOST_HISTOGRAM_DETAIL_AXES_HPP
+#include <array>
#include <boost/assert.hpp>
#include <boost/histogram/axis/traits.hpp>
#include <boost/histogram/axis/variant.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/static_if.hpp>
#include <boost/histogram/fwd.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/tuple.hpp>
+#include <boost/mp11/utility.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
#include <tuple>
#include <type_traits>
+/* Most of the histogram code is generic and works for any number of axes. Buffers with a
+ * fixed maximum capacity are used in some places, which have a size equal to the rank of
+ * a histogram. The buffers are statically allocated to improve performance, which means
+ * that they need a preset maximum capacity. 32 seems like a safe upper limit for the rank
+ * (you can nevertheless increase it here if necessary): the simplest non-trivial axis has
+ * 2 bins; even if counters are used which need only a byte of storage per bin, this still
+ * corresponds to 4 GB of storage.
+ */
+#ifndef BOOST_HISTOGRAM_DETAIL_AXES_LIMIT
+#define BOOST_HISTOGRAM_DETAIL_AXES_LIMIT 32
+#endif
+
namespace boost {
namespace histogram {
namespace detail {
+template <class T>
+unsigned axes_rank(const T& axes) {
+ using std::begin;
+ using std::end;
+ return static_cast<unsigned>(std::distance(begin(axes), end(axes)));
+}
+
+template <class... Ts>
+constexpr unsigned axes_rank(const std::tuple<Ts...>&) {
+ return static_cast<unsigned>(sizeof...(Ts));
+}
+
template <unsigned N, class... Ts>
decltype(auto) axis_get(std::tuple<Ts...>& axes) {
return std::get<N>(axes);
@@ -46,14 +72,18 @@ decltype(auto) axis_get(const T& axes) {
template <class... Ts>
decltype(auto) axis_get(std::tuple<Ts...>& axes, unsigned i) {
- return mp11::mp_with_index<sizeof...(Ts)>(
- i, [&](auto I) { return axis::variant<Ts&...>(std::get<I>(axes)); });
+ using namespace boost::mp11;
+ constexpr auto S = sizeof...(Ts);
+ using V = mp_unique<axis::variant<Ts*...>>;
+ return mp_with_index<S>(i, [&axes](auto i) { return V(&std::get<i>(axes)); });
}
template <class... Ts>
decltype(auto) axis_get(const std::tuple<Ts...>& axes, unsigned i) {
- return mp11::mp_with_index<sizeof...(Ts)>(
- i, [&](auto I) { return axis::variant<const Ts&...>(std::get<I>(axes)); });
+ using namespace boost::mp11;
+ constexpr auto S = sizeof...(Ts);
+ using V = mp_unique<axis::variant<const Ts*...>>;
+ return mp_with_index<S>(i, [&axes](auto i) { return V(&std::get<i>(axes)); });
}
template <class T>
@@ -70,7 +100,7 @@ template <class... Ts, class... Us>
bool axes_equal(const std::tuple<Ts...>& ts, const std::tuple<Us...>& us) {
return static_if<std::is_same<mp11::mp_list<Ts...>, mp11::mp_list<Us...>>>(
[](const auto& ts, const auto& us) {
- using N = mp11::mp_size<remove_cvref_t<decltype(ts)>>;
+ using N = mp11::mp_size<std::decay_t<decltype(ts)>>;
bool equal = true;
mp11::mp_for_each<mp11::mp_iota<N>>(
[&](auto I) { equal &= relaxed_equal(std::get<I>(ts), std::get<I>(us)); });
@@ -79,17 +109,17 @@ bool axes_equal(const std::tuple<Ts...>& ts, const std::tuple<Us...>& us) {
[](const auto&, const auto&) { return false; }, ts, us);
}
-template <class... Ts, class U>
-bool axes_equal(const std::tuple<Ts...>& t, const U& u) {
- if (sizeof...(Ts) != u.size()) return false;
+template <class T, class... Us>
+bool axes_equal(const T& t, const std::tuple<Us...>& u) {
+ if (t.size() != sizeof...(Us)) return false;
bool equal = true;
- mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Ts)>>(
- [&](auto I) { equal &= u[I] == std::get<I>(t); });
+ mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Us)>>(
+ [&](auto I) { equal &= t[I] == std::get<I>(u); });
return equal;
}
-template <class T, class... Us>
-bool axes_equal(const T& t, const std::tuple<Us...>& u) {
+template <class... Ts, class U>
+bool axes_equal(const std::tuple<Ts...>& t, const U& u) {
return axes_equal(u, t);
}
@@ -131,9 +161,23 @@ void axes_assign(T& t, const U& u) {
t.assign(u.begin(), u.end());
}
+// create empty dynamic axis which can store any axes types from the argument
+template <class T>
+auto make_empty_dynamic_axes(const T& axes) {
+ return make_default(axes);
+}
+
+template <class... Ts>
+auto make_empty_dynamic_axes(const std::tuple<Ts...>&) {
+ using namespace ::boost::mp11;
+ using L = mp_unique<axis::variant<Ts...>>;
+ // return std::vector<axis::variant<Axis0, Axis1, ...>> or std::vector<Axis0>
+ return std::vector<mp_if_c<(mp_size<L>::value == 1), mp_first<L>, L>>{};
+}
+
template <typename T>
void axis_index_is_valid(const T& axes, const unsigned N) {
- BOOST_ASSERT_MSG(N < get_size(axes), "index out of range");
+ BOOST_ASSERT_MSG(N < axes_rank(axes), "index out of range");
}
template <typename F, typename T>
@@ -169,6 +213,50 @@ std::size_t bincount(const T& axes) {
return n;
}
+template <class T>
+using tuple_size_t = typename std::tuple_size<T>::type;
+
+template <class T>
+using buffer_size = mp11::mp_eval_or<
+ std::integral_constant<std::size_t, BOOST_HISTOGRAM_DETAIL_AXES_LIMIT>, tuple_size_t,
+ T>;
+
+template <class T, std::size_t N>
+class sub_array : public std::array<T, N> {
+ using base_type = std::array<T, N>;
+
+public:
+ explicit sub_array(std::size_t s) noexcept(
+ std::is_nothrow_default_constructible<T>::value)
+ : size_(s) {
+ BOOST_ASSERT_MSG(size_ <= N, "requested size exceeds size of static buffer");
+ }
+
+ sub_array(std::size_t s,
+ const T& value) noexcept(std::is_nothrow_copy_constructible<T>::value)
+ : size_(s) {
+ BOOST_ASSERT_MSG(size_ <= N, "requested size exceeds size of static buffer");
+ std::array<T, N>::fill(value);
+ }
+
+ // need to override both versions of std::array
+ auto end() noexcept { return base_type::begin() + size_; }
+ auto end() const noexcept { return base_type::begin() + size_; }
+
+ auto size() const noexcept { return size_; }
+
+private:
+ std::size_t size_;
+};
+
+template <class U, class T>
+using stack_buffer = sub_array<U, buffer_size<T>::value>;
+
+template <class U, class T, class... Ts>
+auto make_stack_buffer(const T& t, const Ts&... ts) {
+ return stack_buffer<U, T>(axes_rank(t), ts...);
+}
+
} // namespace detail
} // namespace histogram
} // namespace boost
diff --git a/boost/histogram/detail/common_type.hpp b/boost/histogram/detail/common_type.hpp
index e1a4b66469..848d10a452 100644
--- a/boost/histogram/detail/common_type.hpp
+++ b/boost/histogram/detail/common_type.hpp
@@ -7,7 +7,7 @@
#ifndef BOOST_HISTOGRAM_DETAIL_COMMON_TYPE_HPP
#define BOOST_HISTOGRAM_DETAIL_COMMON_TYPE_HPP
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/detect.hpp>
#include <boost/histogram/fwd.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/utility.hpp>
@@ -26,51 +26,20 @@ using common_axes = mp11::mp_cond<
is_sequence_of_axis<U>, U,
std::true_type, T
>;
-
-template <class T, class U>
-using common_container = mp11::mp_cond<
- is_array_like<T>, T,
- is_array_like<U>, U,
- is_vector_like<T>, T,
- is_vector_like<U>, U,
- std::true_type, T
->;
// clang-format on
-template <class T>
-using type_score = mp11::mp_size_t<((!std::is_pod<T>::value) * 1000 +
- std::is_floating_point<T>::value * 50 + sizeof(T))>;
-
-template <class T, class U>
-struct common_storage_impl;
+// Non-PODs rank highest, then floats, than integers; types with more capacity are higher
+template <class Storage>
+static constexpr std::size_t type_rank() {
+ using T = typename Storage::value_type;
+ return !std::is_pod<T>::value * 10000 + std::is_floating_point<T>::value * 100 +
+ 10 * sizeof(T) + 2 * is_array_like<Storage>::value +
+ is_vector_like<Storage>::value;
+ ;
+}
template <class T, class U>
-struct common_storage_impl<storage_adaptor<T>, storage_adaptor<U>> {
- using type =
- mp11::mp_if_c<(type_score<typename storage_adaptor<T>::value_type>::value >=
- type_score<typename storage_adaptor<U>::value_type>::value),
- storage_adaptor<T>, storage_adaptor<U>>;
-};
-
-template <class T, class A>
-struct common_storage_impl<storage_adaptor<T>, unlimited_storage<A>> {
- using type =
- mp11::mp_if_c<(type_score<typename storage_adaptor<T>::value_type>::value >=
- type_score<typename unlimited_storage<A>::value_type>::value),
- storage_adaptor<T>, unlimited_storage<A>>;
-};
-
-template <class C, class A>
-struct common_storage_impl<unlimited_storage<A>, storage_adaptor<C>>
- : common_storage_impl<storage_adaptor<C>, unlimited_storage<A>> {};
-
-template <class A1, class A2>
-struct common_storage_impl<unlimited_storage<A1>, unlimited_storage<A2>> {
- using type = unlimited_storage<A1>;
-};
-
-template <class A, class B>
-using common_storage = typename common_storage_impl<A, B>::type;
+using common_storage = mp11::mp_if_c<(type_rank<T>() >= type_rank<U>()), T, U>;
} // namespace detail
} // namespace histogram
} // namespace boost
diff --git a/boost/histogram/detail/compressed_pair.hpp b/boost/histogram/detail/compressed_pair.hpp
index 8288e5d8b1..aead2cb59d 100644
--- a/boost/histogram/detail/compressed_pair.hpp
+++ b/boost/histogram/detail/compressed_pair.hpp
@@ -14,59 +14,79 @@ namespace boost {
namespace histogram {
namespace detail {
-template <typename T1, typename T2, bool B>
+template <class T1, class T2, bool B>
class compressed_pair_impl;
-template <typename T1, typename T2>
-class compressed_pair_impl<T1, T2, true> : protected T2 {
+// normal implementation
+template <class T1, class T2>
+class compressed_pair_impl<T1, T2, false> {
public:
- template <typename U1, typename U2>
- compressed_pair_impl(U1&& u1, U2&& u2)
- : T2(std::forward<U2>(u2)), first_(std::forward<U1>(u1)) {}
- template <typename U1>
- compressed_pair_impl(U1&& u1) : first_(std::forward<U1>(u1)) {}
+ using first_type = T1;
+ using second_type = T2;
+
compressed_pair_impl() = default;
- T1& first() { return first_; }
- T2& second() { return static_cast<T2&>(*this); }
- const T1& first() const { return first_; }
- const T2& second() const { return static_cast<const T2&>(*this); }
+ compressed_pair_impl(first_type&& x, second_type&& y)
+ : first_(std::move(x)), second_(std::move(y)) {}
+
+ compressed_pair_impl(const first_type& x, const second_type& y)
+ : first_(x), second_(y) {}
+
+ compressed_pair_impl(first_type&& x) : first_(std::move(x)) {}
+ compressed_pair_impl(const first_type& x) : first_(x) {}
+
+ first_type& first() noexcept { return first_; }
+ second_type& second() noexcept { return second_; }
+ const first_type& first() const noexcept { return first_; }
+ const second_type& second() const noexcept { return second_; }
private:
- T1 first_;
+ first_type first_;
+ second_type second_;
};
-template <typename T1, typename T2>
-class compressed_pair_impl<T1, T2, false> {
+// compressed implementation, T2 consumes no space
+template <class T1, class T2>
+class compressed_pair_impl<T1, T2, true> : protected T2 {
public:
- template <typename U1, typename U2>
- compressed_pair_impl(U1&& u1, U2&& u2)
- : first_(std::forward<U1>(u1)), second_(std::forward<U2>(u2)) {}
- template <typename U1>
- compressed_pair_impl(U1&& u1) : first_(std::forward<U1>(u1)) {}
+ using first_type = T1;
+ using second_type = T2;
+
compressed_pair_impl() = default;
- T1& first() { return first_; }
- T2& second() { return second_; }
- const T1& first() const { return first_; }
- const T2& second() const { return second_; }
+ compressed_pair_impl(first_type&& x, second_type&& y)
+ : T2(std::move(y)), first_(std::move(x)) {}
+
+ compressed_pair_impl(const first_type& x, const second_type& y) : T2(y), first_(x) {}
+
+ compressed_pair_impl(first_type&& x) : first_(std::move(x)) {}
+ compressed_pair_impl(const first_type& x) : first_(x) {}
+
+ first_type& first() noexcept { return first_; }
+ second_type& second() noexcept { return static_cast<second_type&>(*this); }
+ const first_type& first() const noexcept { return first_; }
+ const second_type& second() const noexcept {
+ return static_cast<const second_type&>(*this);
+ }
private:
- T1 first_;
- T2 second_;
+ first_type first_;
};
-template <typename... Ts>
-void swap(compressed_pair_impl<Ts...>& a, compressed_pair_impl<Ts...>& b) {
+template <typename T1, typename T2>
+using compressed_pair =
+ compressed_pair_impl<T1, T2, (!std::is_final<T2>::value && std::is_empty<T2>::value)>;
+
+template <class T, class U>
+void swap(compressed_pair<T, U>& a, compressed_pair<T, U>& b) noexcept(
+ std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_assignable<
+ T>::value&& std::is_nothrow_move_constructible<U>::value&&
+ std::is_nothrow_move_assignable<U>::value) {
using std::swap;
swap(a.first(), b.first());
swap(a.second(), b.second());
}
-template <typename T1, typename T2>
-using compressed_pair =
- compressed_pair_impl<T1, T2, (!std::is_final<T2>::value && std::is_empty<T2>::value)>;
-
} // namespace detail
} // namespace histogram
} // namespace boost
diff --git a/boost/histogram/detail/convert_integer.hpp b/boost/histogram/detail/convert_integer.hpp
new file mode 100644
index 0000000000..bed52f7599
--- /dev/null
+++ b/boost/histogram/detail/convert_integer.hpp
@@ -0,0 +1,24 @@
+// Copyright 2018-2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_CONVERT_INTEGER_HPP
+#define BOOST_HISTOGRAM_DETAIL_CONVERT_INTEGER_HPP
+
+#include <type_traits>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <class T, class U>
+using convert_integer =
+ std::conditional_t<std::is_integral<std::decay_t<T>>::value, U, T>;
+
+}
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/detect.hpp b/boost/histogram/detail/detect.hpp
new file mode 100644
index 0000000000..c1cf87717f
--- /dev/null
+++ b/boost/histogram/detail/detect.hpp
@@ -0,0 +1,209 @@
+// Copyright 2015-2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_DETECT_HPP
+#define BOOST_HISTOGRAM_DETAIL_DETECT_HPP
+
+#include <boost/histogram/fwd.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/function.hpp>
+#include <boost/mp11/utility.hpp>
+#include <iterator>
+#include <tuple>
+#include <type_traits>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+#define BOOST_HISTOGRAM_DETECT(name, cond) \
+ template <class T, class = decltype(cond)> \
+ struct name##_impl {}; \
+ template <class T> \
+ struct name : mp11::mp_valid<name##_impl, T>::type {}
+
+#define BOOST_HISTOGRAM_DETECT_BINARY(name, cond) \
+ template <class T, class U, class = decltype(cond)> \
+ struct name##_impl {}; \
+ template <class T, class U = T> \
+ struct name : mp11::mp_valid<name##_impl, T, U>::type {}
+
+// metadata has overloads, trying to get pmf in this case always fails
+BOOST_HISTOGRAM_DETECT(has_method_metadata, (std::declval<T&>().metadata()));
+
+// resize has overloads, trying to get pmf in this case always fails
+BOOST_HISTOGRAM_DETECT(has_method_resize, (std::declval<T&>().resize(0)));
+
+BOOST_HISTOGRAM_DETECT(has_method_size, &T::size);
+
+BOOST_HISTOGRAM_DETECT(has_method_clear, &T::clear);
+
+BOOST_HISTOGRAM_DETECT(has_method_lower, &T::lower);
+
+BOOST_HISTOGRAM_DETECT(has_method_value, &T::value);
+
+BOOST_HISTOGRAM_DETECT(has_method_update, (&T::update));
+
+// reset has overloads, trying to get pmf in this case always fails
+BOOST_HISTOGRAM_DETECT(has_method_reset, (std::declval<T>().reset(0)));
+
+BOOST_HISTOGRAM_DETECT(has_method_options, (&T::options));
+
+BOOST_HISTOGRAM_DETECT(has_allocator, &T::get_allocator);
+
+BOOST_HISTOGRAM_DETECT(is_indexable, (std::declval<T&>()[0]));
+
+BOOST_HISTOGRAM_DETECT(is_transform, (&T::forward, &T::inverse));
+
+BOOST_HISTOGRAM_DETECT(is_indexable_container,
+ (std::declval<T>()[0], &T::size, std::begin(std::declval<T>()),
+ std::end(std::declval<T>())));
+
+BOOST_HISTOGRAM_DETECT(is_vector_like,
+ (std::declval<T>()[0], &T::size, std::declval<T>().resize(0),
+ std::begin(std::declval<T>()), std::end(std::declval<T>())));
+
+BOOST_HISTOGRAM_DETECT(is_array_like,
+ (std::declval<T>()[0], &T::size, std::tuple_size<T>::value,
+ std::begin(std::declval<T>()), std::end(std::declval<T>())));
+
+BOOST_HISTOGRAM_DETECT(is_map_like,
+ (std::declval<typename T::key_type>(),
+ std::declval<typename T::mapped_type>(),
+ std::begin(std::declval<T>()), std::end(std::declval<T>())));
+
+// ok: is_axis is false for axis::variant, because T::index is templated
+BOOST_HISTOGRAM_DETECT(is_axis, (&T::size, &T::index));
+
+BOOST_HISTOGRAM_DETECT(is_iterable,
+ (std::begin(std::declval<T&>()), std::end(std::declval<T&>())));
+
+BOOST_HISTOGRAM_DETECT(is_iterator,
+ (typename std::iterator_traits<T>::iterator_category()));
+
+BOOST_HISTOGRAM_DETECT(is_streamable,
+ (std::declval<std::ostream&>() << std::declval<T&>()));
+
+BOOST_HISTOGRAM_DETECT(has_operator_preincrement, (++std::declval<T&>()));
+
+BOOST_HISTOGRAM_DETECT_BINARY(has_operator_equal,
+ (std::declval<const T&>() == std::declval<const U>()));
+
+BOOST_HISTOGRAM_DETECT_BINARY(has_operator_radd,
+ (std::declval<T&>() += std::declval<U>()));
+
+BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rsub,
+ (std::declval<T&>() -= std::declval<U>()));
+
+BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rmul,
+ (std::declval<T&>() *= std::declval<U>()));
+
+BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rdiv,
+ (std::declval<T&>() /= std::declval<U>()));
+
+BOOST_HISTOGRAM_DETECT_BINARY(
+ has_method_eq, (std::declval<const T>().operator==(std::declval<const U>())));
+
+BOOST_HISTOGRAM_DETECT(has_threading_support, (T::has_threading_support));
+
+template <typename T>
+struct is_weight_impl : std::false_type {};
+
+template <typename T>
+struct is_weight_impl<weight_type<T>> : std::true_type {};
+
+template <typename T>
+using is_weight = is_weight_impl<std::decay_t<T>>;
+
+template <typename T>
+struct is_sample_impl : std::false_type {};
+
+template <typename T>
+struct is_sample_impl<sample_type<T>> : std::true_type {};
+
+template <typename T>
+using is_sample = is_sample_impl<std::decay_t<T>>;
+
+template <typename T>
+using is_storage = mp11::mp_and<is_indexable_container<T>, has_method_reset<T>,
+ has_threading_support<T>>;
+
+template <class T>
+using is_adaptible = mp11::mp_or<is_vector_like<T>, is_array_like<T>, is_map_like<T>>;
+
+template <class T, class _ = std::decay_t<T>,
+ class = std::enable_if_t<(is_storage<_>::value || is_adaptible<_>::value)>>
+struct requires_storage_or_adaptible {};
+
+template <typename T>
+struct is_tuple_impl : std::false_type {};
+
+template <typename... Ts>
+struct is_tuple_impl<std::tuple<Ts...>> : std::true_type {};
+
+template <typename T>
+using is_tuple = typename is_tuple_impl<T>::type;
+
+template <typename T>
+struct is_axis_variant_impl : std::false_type {};
+
+template <typename... Ts>
+struct is_axis_variant_impl<axis::variant<Ts...>> : std::true_type {};
+
+template <typename T>
+using is_axis_variant = typename is_axis_variant_impl<T>::type;
+
+template <typename T>
+using is_any_axis = mp11::mp_or<is_axis<T>, is_axis_variant<T>>;
+
+template <typename T>
+using is_sequence_of_axis = mp11::mp_and<is_iterable<T>, is_axis<mp11::mp_first<T>>>;
+
+template <typename T>
+using is_sequence_of_axis_variant =
+ mp11::mp_and<is_iterable<T>, is_axis_variant<mp11::mp_first<T>>>;
+
+template <typename T>
+using is_sequence_of_any_axis =
+ mp11::mp_and<is_iterable<T>, is_any_axis<mp11::mp_first<T>>>;
+
+// poor-mans concept checks
+template <class T, class = std::enable_if_t<is_iterator<std::decay_t<T>>::value>>
+struct requires_iterator {};
+
+template <class T, class = std::enable_if_t<
+ is_iterable<std::remove_cv_t<std::remove_reference_t<T>>>::value>>
+struct requires_iterable {};
+
+template <class T, class = std::enable_if_t<is_axis<std::decay_t<T>>::value>>
+struct requires_axis {};
+
+template <class T, class = std::enable_if_t<is_any_axis<std::decay_t<T>>::value>>
+struct requires_any_axis {};
+
+template <class T, class = std::enable_if_t<is_sequence_of_axis<std::decay_t<T>>::value>>
+struct requires_sequence_of_axis {};
+
+template <class T,
+ class = std::enable_if_t<is_sequence_of_axis_variant<std::decay_t<T>>::value>>
+struct requires_sequence_of_axis_variant {};
+
+template <class T,
+ class = std::enable_if_t<is_sequence_of_any_axis<std::decay_t<T>>::value>>
+struct requires_sequence_of_any_axis {};
+
+template <class T,
+ class = std::enable_if_t<is_any_axis<mp11::mp_first<std::decay_t<T>>>::value>>
+struct requires_axes {};
+
+template <class T, class U, class = std::enable_if_t<std::is_convertible<T, U>::value>>
+struct requires_convertible {};
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/iterator_adaptor.hpp b/boost/histogram/detail/iterator_adaptor.hpp
new file mode 100644
index 0000000000..345a4abb19
--- /dev/null
+++ b/boost/histogram/detail/iterator_adaptor.hpp
@@ -0,0 +1,162 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Uses code segments from boost/iterator/iterator_adaptor.hpp
+// and boost/iterator/iterator_fascade.hpp
+
+#ifndef BOOST_HISTOGRAM_DETAIL_ITERATOR_ADAPTOR_HPP
+#define BOOST_HISTOGRAM_DETAIL_ITERATOR_ADAPTOR_HPP
+
+#include <iterator>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+// operator->() needs special support for input iterators to strictly meet the
+// standard's requirements. If *i is not a reference type, we must still
+// produce an lvalue to which a pointer can be formed. We do that by
+// returning a proxy object containing an instance of the reference object.
+template <class Reference>
+struct operator_arrow_dispatch_t // proxy references
+{
+ struct proxy {
+ explicit proxy(Reference const& x) noexcept : m_ref(x) {}
+ Reference* operator->() noexcept { return std::addressof(m_ref); }
+ Reference m_ref;
+ };
+
+ using result_type = proxy;
+ static result_type apply(Reference const& x) noexcept { return proxy(x); }
+};
+
+template <class T>
+struct operator_arrow_dispatch_t<T&> // "real" references
+{
+ using result_type = T*;
+ static result_type apply(T& x) noexcept { return std::addressof(x); }
+};
+
+// only for random access Base
+template <class Derived, class Base, class Reference = std::remove_pointer_t<Base>&,
+ class Value = std::decay_t<Reference>>
+class iterator_adaptor {
+ using operator_arrow_dispatch = operator_arrow_dispatch_t<Reference>;
+
+public:
+ using base_type = Base;
+
+ using reference = Reference;
+ using value_type = std::remove_const_t<Value>;
+ using pointer = typename operator_arrow_dispatch::result_type;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::random_access_iterator_tag;
+
+ iterator_adaptor() = default;
+
+ explicit iterator_adaptor(base_type const& iter) : iter_(iter) {}
+
+ pointer operator->() const noexcept {
+ return operator_arrow_dispatch::apply(this->derived().operator*());
+ }
+ reference operator[](difference_type n) const { return *(this->derived() + n); }
+
+ Derived& operator++() {
+ ++iter_;
+ return this->derived();
+ }
+
+ Derived& operator--() {
+ --iter_;
+ return this->derived();
+ }
+
+ Derived operator++(int) {
+ Derived tmp(this->derived());
+ ++iter_;
+ return tmp;
+ }
+
+ Derived operator--(int) {
+ Derived tmp(this->derived());
+ --iter_;
+ return tmp;
+ }
+
+ Derived& operator+=(difference_type n) {
+ iter_ += n;
+ return this->derived();
+ }
+
+ Derived& operator-=(difference_type n) {
+ iter_ -= n;
+ return this->derived();
+ }
+
+ Derived operator+(difference_type n) const {
+ Derived tmp(this->derived());
+ tmp += n;
+ return tmp;
+ }
+
+ Derived operator-(difference_type n) const { return operator+(-n); }
+
+ template <class... Ts>
+ difference_type operator-(const iterator_adaptor<Ts...>& x) const noexcept {
+ return iter_ - x.iter_;
+ }
+
+ template <class... Ts>
+ bool operator==(const iterator_adaptor<Ts...>& x) const noexcept {
+ return iter_ == x.iter_;
+ }
+ template <class... Ts>
+ bool operator!=(const iterator_adaptor<Ts...>& x) const noexcept {
+ return !this->derived().operator==(x); // equal operator may be overridden in derived
+ }
+ template <class... Ts>
+ bool operator<(const iterator_adaptor<Ts...>& x) const noexcept {
+ return iter_ < x.iter_;
+ }
+ template <class... Ts>
+ bool operator>(const iterator_adaptor<Ts...>& x) const noexcept {
+ return iter_ > x.iter_;
+ }
+ template <class... Ts>
+ bool operator<=(const iterator_adaptor<Ts...>& x) const noexcept {
+ return iter_ <= x.iter_;
+ }
+ template <class... Ts>
+ bool operator>=(const iterator_adaptor<Ts...>& x) const noexcept {
+ return iter_ >= x.iter_;
+ }
+
+ friend Derived operator+(difference_type n, const Derived& x) { return x + n; }
+
+ Base const& base() const noexcept { return iter_; }
+
+protected:
+ // for convenience in derived classes
+ using iterator_adaptor_ = iterator_adaptor;
+
+private:
+ Derived& derived() noexcept { return *static_cast<Derived*>(this); }
+ const Derived& derived() const noexcept { return *static_cast<Derived const*>(this); }
+
+ Base iter_;
+
+ template <class, class, class, class>
+ friend class iterator_adaptor;
+};
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/large_int.hpp b/boost/histogram/detail/large_int.hpp
new file mode 100644
index 0000000000..2259cbda5f
--- /dev/null
+++ b/boost/histogram/detail/large_int.hpp
@@ -0,0 +1,227 @@
+// Copyright 2018-2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_LARGE_INT_HPP
+#define BOOST_HISTOGRAM_DETAIL_LARGE_INT_HPP
+
+#include <boost/assert.hpp>
+#include <boost/histogram/detail/operators.hpp>
+#include <boost/histogram/detail/safe_comparison.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/function.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+#include <cmath>
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <class T>
+using is_unsigned_integral = mp11::mp_and<std::is_integral<T>, std::is_unsigned<T>>;
+
+template <class T>
+bool safe_increment(T& t) {
+ if (t < std::numeric_limits<T>::max()) {
+ ++t;
+ return true;
+ }
+ return false;
+}
+
+template <class T, class U>
+bool safe_radd(T& t, const U& u) {
+ static_assert(is_unsigned_integral<T>::value, "T must be unsigned integral type");
+ static_assert(is_unsigned_integral<U>::value, "T must be unsigned integral type");
+ if (static_cast<T>(std::numeric_limits<T>::max() - t) >= u) {
+ t += static_cast<T>(u); // static_cast to suppress conversion warning
+ return true;
+ }
+ return false;
+}
+
+// An integer type which can grow arbitrarily large (until memory is exhausted).
+// Use boost.multiprecision.cpp_int in your own code, it is much more sophisticated.
+// We use it only to reduce coupling between boost libs.
+template <class Allocator>
+struct large_int : totally_ordered<large_int<Allocator>, large_int<Allocator>>,
+ partially_ordered<large_int<Allocator>, void> {
+ explicit large_int(const Allocator& a = {}) : data(1, 0, a) {}
+ explicit large_int(std::uint64_t v, const Allocator& a = {}) : data(1, v, a) {}
+
+ large_int(const large_int&) = default;
+ large_int& operator=(const large_int&) = default;
+ large_int(large_int&&) = default;
+ large_int& operator=(large_int&&) = default;
+
+ large_int& operator=(std::uint64_t o) {
+ data = decltype(data)(1, o);
+ return *this;
+ }
+
+ large_int& operator++() {
+ BOOST_ASSERT(data.size() > 0u);
+ std::size_t i = 0;
+ while (!safe_increment(data[i])) {
+ data[i] = 0;
+ ++i;
+ if (i == data.size()) {
+ data.push_back(1);
+ break;
+ }
+ }
+ return *this;
+ }
+
+ large_int& operator+=(const large_int& o) {
+ if (this == &o) {
+ auto tmp{o};
+ return operator+=(tmp);
+ }
+ bool carry = false;
+ std::size_t i = 0;
+ for (std::uint64_t oi : o.data) {
+ auto& di = maybe_extend(i);
+ if (carry) {
+ if (safe_increment(oi))
+ carry = false;
+ else {
+ ++i;
+ continue;
+ }
+ }
+ if (!safe_radd(di, oi)) {
+ add_remainder(di, oi);
+ carry = true;
+ }
+ ++i;
+ }
+ while (carry) {
+ auto& di = maybe_extend(i);
+ if (safe_increment(di)) break;
+ di = 0;
+ ++i;
+ }
+ return *this;
+ }
+
+ large_int& operator+=(std::uint64_t o) {
+ BOOST_ASSERT(data.size() > 0u);
+ if (safe_radd(data[0], o)) return *this;
+ add_remainder(data[0], o);
+ // carry the one, data may grow several times
+ std::size_t i = 1;
+ while (true) {
+ auto& di = maybe_extend(i);
+ if (safe_increment(di)) break;
+ di = 0;
+ ++i;
+ }
+ return *this;
+ }
+
+ explicit operator double() const noexcept {
+ BOOST_ASSERT(data.size() > 0u);
+ double result = static_cast<double>(data[0]);
+ std::size_t i = 0;
+ while (++i < data.size())
+ result += static_cast<double>(data[i]) * std::pow(2.0, i * 64);
+ return result;
+ }
+
+ bool operator<(const large_int& o) const noexcept {
+ BOOST_ASSERT(data.size() > 0u);
+ BOOST_ASSERT(o.data.size() > 0u);
+ // no leading zeros allowed
+ BOOST_ASSERT(data.size() == 1 || data.back() > 0u);
+ BOOST_ASSERT(o.data.size() == 1 || o.data.back() > 0u);
+ if (data.size() < o.data.size()) return true;
+ if (data.size() > o.data.size()) return false;
+ auto s = data.size();
+ while (s > 0u) {
+ --s;
+ if (data[s] < o.data[s]) return true;
+ if (data[s] > o.data[s]) return false;
+ }
+ return false; // args are equal
+ }
+
+ bool operator==(const large_int& o) const noexcept {
+ BOOST_ASSERT(data.size() > 0u);
+ BOOST_ASSERT(o.data.size() > 0u);
+ // no leading zeros allowed
+ BOOST_ASSERT(data.size() == 1 || data.back() > 0u);
+ BOOST_ASSERT(o.data.size() == 1 || o.data.back() > 0u);
+ if (data.size() != o.data.size()) return false;
+ return std::equal(data.begin(), data.end(), o.data.begin());
+ }
+
+ template <class U>
+ std::enable_if_t<std::is_integral<U>::value, bool> operator<(const U& o) const
+ noexcept {
+ BOOST_ASSERT(data.size() > 0u);
+ return data.size() == 1 && safe_less()(data[0], o);
+ }
+
+ template <class U>
+ std::enable_if_t<std::is_integral<U>::value, bool> operator>(const U& o) const
+ noexcept {
+ BOOST_ASSERT(data.size() > 0u);
+ BOOST_ASSERT(data.size() == 1 || data.back() > 0u); // no leading zeros allowed
+ return data.size() > 1 || safe_less()(o, data[0]);
+ }
+
+ template <class U>
+ std::enable_if_t<std::is_integral<U>::value, bool> operator==(const U& o) const
+ noexcept {
+ BOOST_ASSERT(data.size() > 0u);
+ return data.size() == 1 && safe_equal()(data[0], o);
+ }
+
+ template <class U>
+ std::enable_if_t<std::is_floating_point<U>::value, bool> operator<(const U& o) const
+ noexcept {
+ return operator double() < o;
+ }
+ template <class U>
+ std::enable_if_t<std::is_floating_point<U>::value, bool> operator>(const U& o) const
+ noexcept {
+ return operator double() > o;
+ }
+ template <class U>
+ std::enable_if_t<std::is_floating_point<U>::value, bool> operator==(const U& o) const
+ noexcept {
+ return operator double() == o;
+ }
+
+ std::uint64_t& maybe_extend(std::size_t i) {
+ while (i >= data.size()) data.push_back(0);
+ return data[i];
+ }
+
+ static void add_remainder(std::uint64_t& d, const std::uint64_t o) noexcept {
+ BOOST_ASSERT(d > 0u);
+ // in decimal system it would look like this:
+ // 8 + 8 = 6 = 8 - (9 - 8) - 1
+ // 9 + 1 = 0 = 9 - (9 - 1) - 1
+ auto tmp = std::numeric_limits<std::uint64_t>::max();
+ tmp -= o;
+ --d -= tmp;
+ }
+
+ std::vector<std::uint64_t, Allocator> data;
+};
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/limits.hpp b/boost/histogram/detail/limits.hpp
new file mode 100644
index 0000000000..23b8a6f1c5
--- /dev/null
+++ b/boost/histogram/detail/limits.hpp
@@ -0,0 +1,50 @@
+// Copyright 2015-2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_LIMITS_HPP
+#define BOOST_HISTOGRAM_DETAIL_LIMITS_HPP
+
+#include <limits>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <typename T>
+constexpr T lowest() {
+ return std::numeric_limits<T>::lowest();
+}
+
+template <>
+constexpr double lowest() {
+ return -std::numeric_limits<double>::infinity();
+}
+
+template <>
+constexpr float lowest() {
+ return -std::numeric_limits<float>::infinity();
+}
+
+template <typename T>
+constexpr T highest() {
+ return std::numeric_limits<T>::max();
+}
+
+template <>
+constexpr double highest() {
+ return std::numeric_limits<double>::infinity();
+}
+
+template <>
+constexpr float highest() {
+ return std::numeric_limits<float>::infinity();
+}
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/linearize.hpp b/boost/histogram/detail/linearize.hpp
index e07590ab4d..b24be8efbd 100644
--- a/boost/histogram/detail/linearize.hpp
+++ b/boost/histogram/detail/linearize.hpp
@@ -11,16 +11,19 @@
#include <boost/assert.hpp>
#include <boost/histogram/axis/traits.hpp>
#include <boost/histogram/axis/variant.hpp>
+#include <boost/histogram/detail/args_type.hpp>
#include <boost/histogram/detail/axes.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/make_default.hpp>
+#include <boost/histogram/detail/static_if.hpp>
+#include <boost/histogram/detail/tuple_slice.hpp>
#include <boost/histogram/fwd.hpp>
-#include <boost/histogram/unsafe_access.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/function.hpp>
#include <boost/mp11/integral.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/tuple.hpp>
#include <boost/throw_exception.hpp>
+#include <mutex>
#include <stdexcept>
#include <tuple>
#include <type_traits>
@@ -30,25 +33,33 @@ namespace histogram {
namespace detail {
template <class T>
-struct is_accumulator_set : std::false_type {};
-
-template <class T>
using has_underflow =
decltype(axis::traits::static_options<T>::test(axis::option::underflow));
template <class T>
-struct is_growing
- : decltype(axis::traits::static_options<T>::test(axis::option::growth)) {};
+using is_growing = decltype(axis::traits::static_options<T>::test(axis::option::growth));
+
+template <class T>
+using is_multidim = is_tuple<std::decay_t<arg_type<decltype(&T::index)>>>;
+
+template <template <class> class Trait, class T>
+struct has_special_axis_impl : Trait<T> {};
+
+template <template <class> class Trait, class... Ts>
+struct has_special_axis_impl<Trait, std::tuple<Ts...>> : mp11::mp_or<Trait<Ts>...> {};
-template <class... Ts>
-struct is_growing<std::tuple<Ts...>> : mp11::mp_or<is_growing<Ts>...> {};
+template <template <class> class Trait, class... Ts>
+struct has_special_axis_impl<Trait, axis::variant<Ts...>> : mp11::mp_or<Trait<Ts>...> {};
-template <class... Ts>
-struct is_growing<axis::variant<Ts...>> : mp11::mp_or<is_growing<Ts>...> {};
+template <template <class> class Trait, class T>
+using has_special_axis =
+ has_special_axis_impl<Trait, mp11::mp_if<is_vector_like<T>, mp11::mp_first<T>, T>>;
template <class T>
-using has_growing_axis =
- mp11::mp_if<is_vector_like<T>, is_growing<mp11::mp_first<T>>, is_growing<T>>;
+using has_multidim_axis = has_special_axis<is_multidim, T>;
+
+template <class T>
+using has_growing_axis = has_special_axis<is_growing, T>;
/// Index with an invalid state
struct optional_index {
@@ -58,64 +69,85 @@ struct optional_index {
std::size_t operator*() const { return idx; }
};
-inline void linearize(optional_index& out, const axis::index_type extent,
- const axis::index_type j) noexcept {
- // j is internal index shifted by +1 if axis has underflow bin
- out.idx += j * out.stride;
- // set stride to 0, if j is invalid
- out.stride *= (0 <= j && j < extent) * extent;
+// no underflow, no overflow
+inline void linearize(std::false_type, std::false_type, optional_index& out,
+ const axis::index_type size, const axis::index_type i) noexcept {
+ out.idx += i * out.stride;
+ out.stride *= i >= 0 && i < size ? size : 0;
+}
+
+// no underflow, overflow
+inline void linearize(std::false_type, std::true_type, optional_index& out,
+ const axis::index_type size, const axis::index_type i) noexcept {
+ BOOST_ASSERT(i <= size);
+ out.idx += i * out.stride;
+ out.stride *= i >= 0 ? size + 1 : 0;
+}
+
+// underflow, no overflow
+inline void linearize(std::true_type, std::false_type, optional_index& out,
+ const axis::index_type size, const axis::index_type i) noexcept {
+ // internal index must be shifted by +1 since axis has underflow bin
+ BOOST_ASSERT(i + 1 >= 0);
+ out.idx += (i + 1) * out.stride;
+ out.stride *= i < size ? size + 1 : 0;
+}
+
+// underflow, overflow
+inline void linearize(std::true_type, std::true_type, optional_index& out,
+ const axis::index_type size, const axis::index_type i) noexcept {
+ // internal index must be shifted by +1 since axis has underflow bin
+ BOOST_ASSERT(i + 1 >= 0);
+ BOOST_ASSERT(i <= size);
+ out.idx += (i + 1) * out.stride;
+ out.stride *= size + 2;
}
-// for non-growing axis
template <class Axis, class Value>
void linearize_value(optional_index& o, const Axis& a, const Value& v) {
- using B = decltype(axis::traits::static_options<Axis>::test(axis::option::underflow));
- const auto j = axis::traits::index(a, v) + B::value;
- linearize(o, axis::traits::extent(a), j);
+ using O = axis::traits::static_options<Axis>;
+ linearize(O::test(axis::option::underflow), O::test(axis::option::overflow), o,
+ a.size(), axis::traits::index(a, v));
}
-// for variant that does not contain any growing axis
template <class... Ts, class Value>
void linearize_value(optional_index& o, const axis::variant<Ts...>& a, const Value& v) {
axis::visit([&o, &v](const auto& a) { linearize_value(o, a, v); }, a);
}
-// for growing axis
template <class Axis, class Value>
-void linearize_value(optional_index& o, axis::index_type& s, Axis& a, const Value& v) {
- axis::index_type j;
- std::tie(j, s) = axis::traits::update(a, v);
- j += has_underflow<Axis>::value;
- linearize(o, axis::traits::extent(a), j);
+axis::index_type linearize_value_growth(optional_index& o, Axis& a, const Value& v) {
+ using O = axis::traits::static_options<Axis>;
+ axis::index_type i, s;
+ std::tie(i, s) = axis::traits::update(a, v);
+ linearize(O::test(axis::option::underflow), O::test(axis::option::overflow), o,
+ a.size(), i);
+ return s;
}
-// for variant which contains at least one growing axis
template <class... Ts, class Value>
-void linearize_value(optional_index& o, axis::index_type& s, axis::variant<Ts...>& a,
- const Value& v) {
- axis::visit([&o, &s, &v](auto&& a) { linearize_value(o, s, a, v); }, a);
+axis::index_type linearize_value_growth(optional_index& o, axis::variant<Ts...>& a,
+ const Value& v) {
+ return axis::visit([&o, &v](auto& a) { return linearize_value_growth(o, a, v); }, a);
}
template <class A>
-void linearize_index(optional_index& out, const A& axis, const axis::index_type j) {
+void linearize_index(optional_index& out, const A& axis, const axis::index_type i) {
// A may be axis or variant, cannot use static option detection here
const auto opt = axis::traits::options(axis);
const auto shift = opt & axis::option::underflow ? 1 : 0;
- const auto n = axis.size() + (opt & axis::option::overflow ? 1 : 0);
- linearize(out, n + shift, j + shift);
+ const auto extent = axis.size() + (opt & axis::option::overflow ? 1 : 0) + shift;
+ // i may be arbitrarily out of range
+ linearize(std::false_type{}, std::false_type{}, out, extent, i + shift);
}
-template <class S, class A, class T>
-void maybe_replace_storage(S& storage, const A& axes, const T& shifts) {
- bool update_needed = false;
- auto sit = shifts;
- for_each_axis(axes, [&](const auto&) { update_needed |= (*sit++ != 0); });
- if (!update_needed) return;
+template <class S, class A>
+void grow_storage(const A& axes, S& storage, const axis::index_type* shifts) {
struct item {
axis::index_type idx, old_extent;
std::size_t new_stride;
} data[buffer_size<A>::value];
- sit = shifts;
+ const auto* sit = shifts;
auto dit = data;
std::size_t s = 1;
for_each_axis(axes, [&](const auto& a) {
@@ -124,8 +156,8 @@ void maybe_replace_storage(S& storage, const A& axes, const T& shifts) {
s *= n;
});
auto new_storage = make_default(storage);
- new_storage.reset(detail::bincount(axes));
- const auto dlast = data + get_size(axes) - 1;
+ new_storage.reset(bincount(axes));
+ const auto dlast = data + axes_rank(axes) - 1;
for (const auto& x : storage) {
auto ns = new_storage.begin();
sit = shifts;
@@ -170,6 +202,30 @@ void maybe_replace_storage(S& storage, const A& axes, const T& shifts) {
storage = std::move(new_storage);
}
+// histogram has no growing and no multidim axis, axis rank known at compile-time
+template <class S, class... As, class... Us>
+optional_index index(std::false_type, std::false_type, const std::tuple<As...>& axes, S&,
+ const std::tuple<Us...>& args) {
+ optional_index idx;
+ static_assert(sizeof...(As) == sizeof...(Us), "number of arguments != histogram rank");
+ mp11::mp_for_each<mp11::mp_iota_c<sizeof...(As)>>(
+ [&](auto i) { linearize_value(idx, axis_get<i>(axes), std::get<i>(args)); });
+ return idx;
+}
+
+// histogram has no growing and no multidim axis, axis rank known at run-time
+template <class A, class S, class U>
+optional_index index(std::false_type, std::false_type, const A& axes, S&, const U& args) {
+ constexpr auto nargs = static_cast<unsigned>(std::tuple_size<U>::value);
+ optional_index idx;
+ if (axes_rank(axes) != nargs)
+ BOOST_THROW_EXCEPTION(std::invalid_argument("number of arguments != histogram rank"));
+ constexpr auto nbuf = buffer_size<A>::value;
+ mp11::mp_for_each<mp11::mp_iota_c<(nargs < nbuf ? nargs : nbuf)>>(
+ [&](auto i) { linearize_value(idx, axis_get<i>(axes), std::get<i>(args)); });
+ return idx;
+}
+
// special case: if histogram::operator()(tuple(1, 2)) is called on 1d histogram
// with axis that accepts 2d tuple, this should not fail
// - solution is to forward tuples of size > 1 directly to axis for 1d
@@ -179,55 +235,78 @@ void maybe_replace_storage(S& storage, const A& axes, const T& shifts) {
// (axis::variant provides generic call interface and hides concrete
// interface), so we throw at runtime if incompatible argument is passed (e.g.
// 3d tuple)
-// histogram has only non-growing axes
-template <unsigned I, unsigned N, class S, class T, class U>
-optional_index args_to_index(std::false_type, S&, const T& axes, const U& args) {
+
+// histogram has no growing multidim axis, axis rank == 1 known at compile-time
+template <class S, class A, class U>
+optional_index index(std::false_type, std::true_type, const std::tuple<A>& axes, S&,
+ const U& args) {
optional_index idx;
- const auto rank = get_size(axes);
- if (rank == 1 && N > 1)
- linearize_value(idx, axis_get<0>(axes), tuple_slice<I, N>(args));
+ linearize_value(idx, axis_get<0>(axes), args);
+ return idx;
+}
+
+// histogram has no growing multidim axis, axis rank > 1 known at compile-time
+template <class S, class U, class A0, class A1, class... As>
+optional_index index(std::false_type, std::true_type,
+ const std::tuple<A0, A1, As...>& axes, S& s, const U& args) {
+ return index(std::false_type{}, std::false_type{}, axes, s, args);
+}
+
+// histogram has no growing multidim axis, axis rank known at run-time
+template <class A, class S, class U>
+optional_index index(std::false_type, std::true_type, const A& axes, S&, const U& args) {
+ optional_index idx;
+ const auto rank = axes_rank(axes);
+ constexpr auto nargs = static_cast<unsigned>(std::tuple_size<U>::value);
+ if (rank == 1 && nargs > 1)
+ linearize_value(idx, axis_get<0>(axes), args);
else {
- if (rank != N)
+ if (rank != nargs)
BOOST_THROW_EXCEPTION(
std::invalid_argument("number of arguments != histogram rank"));
- constexpr unsigned M = buffer_size<remove_cvref_t<decltype(axes)>>::value;
- mp11::mp_for_each<mp11::mp_iota_c<(N < M ? N : M)>>([&](auto J) {
- linearize_value(idx, axis_get<J>(axes), std::get<(J + I)>(args));
- });
+ constexpr auto nbuf = buffer_size<A>::value;
+ mp11::mp_for_each<mp11::mp_iota_c<(nargs < nbuf ? nargs : nbuf)>>(
+ [&](auto i) { linearize_value(idx, axis_get<i>(axes), std::get<i>(args)); });
}
return idx;
}
-// histogram has growing axes
-template <unsigned I, unsigned N, class S, class T, class U>
-optional_index args_to_index(std::true_type, S& storage, T& axes, const U& args) {
+// histogram has growing axis
+template <class B, class T, class S, class U>
+optional_index index(std::true_type, B, T& axes, S& storage, const U& args) {
optional_index idx;
- axis::index_type shifts[buffer_size<T>::value];
- const auto rank = get_size(axes);
- if (rank == 1 && N > 1)
- linearize_value(idx, shifts[0], axis_get<0>(axes), tuple_slice<I, N>(args));
- else {
- if (rank != N)
+ constexpr unsigned nbuf = buffer_size<T>::value;
+ axis::index_type shifts[nbuf];
+ const auto rank = axes_rank(axes);
+ constexpr auto nargs = static_cast<unsigned>(std::tuple_size<U>::value);
+
+ bool update_needed = false;
+ if (rank == 1 && nargs > 1) {
+ shifts[0] = linearize_value_growth(idx, axis_get<0>(axes), args);
+ update_needed = (shifts[0] != 0);
+ } else {
+ if (rank != nargs)
BOOST_THROW_EXCEPTION(
std::invalid_argument("number of arguments != histogram rank"));
- constexpr unsigned M = buffer_size<remove_cvref_t<decltype(axes)>>::value;
- mp11::mp_for_each<mp11::mp_iota_c<(N < M ? N : M)>>([&](auto J) {
- linearize_value(idx, shifts[J], axis_get<J>(axes), std::get<(J + I)>(args));
+ mp11::mp_for_each<mp11::mp_iota_c<(nargs < nbuf ? nargs : nbuf)>>([&](auto i) {
+ shifts[i] = linearize_value_growth(idx, axis_get<i>(axes), std::get<i>(args));
+ update_needed |= (shifts[i] != 0);
});
}
- maybe_replace_storage(storage, axes, shifts);
+
+ if (update_needed) grow_storage(axes, storage, shifts);
return idx;
}
-template <typename U>
-constexpr auto weight_sample_indices() {
+template <class U>
+constexpr auto weight_sample_indices() noexcept {
if (is_weight<U>::value) return std::make_pair(0, -1);
if (is_sample<U>::value) return std::make_pair(-1, 0);
return std::make_pair(-1, -1);
}
-template <typename U0, typename U1, typename... Us>
-constexpr auto weight_sample_indices() {
+template <class U0, class U1, class... Us>
+constexpr auto weight_sample_indices() noexcept {
using L = mp11::mp_list<U0, U1, Us...>;
const int n = sizeof...(Us) + 1;
if (is_weight<mp11::mp_at_c<L, 0>>::value) {
@@ -254,72 +333,71 @@ constexpr auto weight_sample_indices() {
}
template <class T, class U>
-void fill_storage(mp11::mp_int<-1>, mp11::mp_int<-1>, T&& t, U&&) {
- static_if<is_incrementable<remove_cvref_t<T>>>(
- [](auto&& t) { ++t; }, [](auto&& t) { t(); }, std::forward<T>(t));
+void fill_impl(mp11::mp_int<-1>, mp11::mp_int<-1>, std::false_type, T&& t,
+ const U&) noexcept {
+ t();
+}
+
+template <class T, class U>
+void fill_impl(mp11::mp_int<-1>, mp11::mp_int<-1>, std::true_type, T&& t,
+ const U&) noexcept {
+ ++t;
}
template <class IW, class T, class U>
-void fill_storage(IW, mp11::mp_int<-1>, T&& t, U&& args) {
- static_if<is_incrementable<remove_cvref_t<T>>>(
- [](auto&& t, const auto& w) { t += w; },
- [](auto&& t, const auto& w) {
-#ifdef BOOST_HISTOGRAM_WITH_ACCUMULATORS_SUPPORT
- static_if<is_accumulator_set<remove_cvref_t<T>>>(
- [w](auto&& t) { t(::boost::accumulators::weight = w); },
- [w](auto&& t) { t(w); }, t);
-#else
- t(w);
-#endif
- },
- std::forward<T>(t), std::get<IW::value>(args).value);
+void fill_impl(IW, mp11::mp_int<-1>, std::false_type, T&& t, const U& u) noexcept {
+ t(std::get<IW::value>(u).value);
+}
+
+template <class IW, class T, class U>
+void fill_impl(IW, mp11::mp_int<-1>, std::true_type, T&& t, const U& u) noexcept {
+ t += std::get<IW::value>(u).value;
}
template <class IS, class T, class U>
-void fill_storage(mp11::mp_int<-1>, IS, T&& t, U&& args) {
- mp11::tuple_apply([&t](auto&&... args) { t(args...); },
- std::get<IS::value>(args).value);
+void fill_impl(mp11::mp_int<-1>, IS, std::false_type, T&& t, const U& u) noexcept {
+ mp11::tuple_apply([&t](auto&&... args) { t(args...); }, std::get<IS::value>(u).value);
}
template <class IW, class IS, class T, class U>
-void fill_storage(IW, IS, T&& t, U&& args) {
- mp11::tuple_apply(
- [&](auto&&... args2) { t(std::get<IW::value>(args).value, args2...); },
- std::get<IS::value>(args).value);
+void fill_impl(IW, IS, std::false_type, T&& t, const U& u) noexcept {
+ mp11::tuple_apply([&](auto&&... args2) { t(std::get<IW::value>(u).value, args2...); },
+ std::get<IS::value>(u).value);
}
-template <class S, class A, class... Us>
-auto fill(S& storage, A& axes, const std::tuple<Us...>& args) {
+template <class A, class S, class... Us>
+typename S::iterator fill(A& axes, S& storage, const std::tuple<Us...>& tus) {
constexpr auto iws = weight_sample_indices<Us...>();
constexpr unsigned n = sizeof...(Us) - (iws.first > -1) - (iws.second > -1);
constexpr unsigned i = (iws.first == 0 || iws.second == 0)
? (iws.first == 1 || iws.second == 1 ? 2 : 1)
: 0;
- optional_index idx = args_to_index<i, n>(has_growing_axis<A>(), storage, axes, args);
+ const auto idx = index(has_growing_axis<A>{}, has_multidim_axis<A>{}, axes, storage,
+ tuple_slice<i, n>(tus));
if (idx) {
- fill_storage(mp11::mp_int<iws.first>(), mp11::mp_int<iws.second>(), storage[*idx],
- args);
+ fill_impl(mp11::mp_int<iws.first>{}, mp11::mp_int<iws.second>{},
+ has_operator_preincrement<typename S::value_type>{}, storage[*idx], tus);
return storage.begin() + *idx;
}
return storage.end();
}
-template <typename A, typename... Us>
+template <class A, class... Us>
optional_index at(const A& axes, const std::tuple<Us...>& args) {
- if (get_size(axes) != sizeof...(Us))
+ if (axes_rank(axes) != sizeof...(Us))
BOOST_THROW_EXCEPTION(std::invalid_argument("number of arguments != histogram rank"));
optional_index idx;
- mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Us)>>([&](auto I) {
+ mp11::mp_for_each<mp11::mp_iota_c<sizeof...(Us)>>([&](auto i) {
// axes_get works with static and dynamic axes
- linearize_index(idx, axis_get<I>(axes),
- static_cast<axis::index_type>(std::get<I>(args)));
+ linearize_index(idx, axis_get<i>(axes),
+ static_cast<axis::index_type>(std::get<i>(args)));
});
return idx;
}
-template <typename A, typename U>
+template <class A, class U>
optional_index at(const A& axes, const U& args) {
- if (get_size(axes) != get_size(args))
+ if (axes_rank(axes) != axes_rank(args))
BOOST_THROW_EXCEPTION(std::invalid_argument("number of arguments != histogram rank"));
optional_index idx;
using std::begin;
diff --git a/boost/histogram/detail/make_default.hpp b/boost/histogram/detail/make_default.hpp
new file mode 100644
index 0000000000..738bde6fb6
--- /dev/null
+++ b/boost/histogram/detail/make_default.hpp
@@ -0,0 +1,27 @@
+// Copyright 2015-2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_MAKE_DEFAULT_HPP
+#define BOOST_HISTOGRAM_DETAIL_MAKE_DEFAULT_HPP
+
+#include <boost/histogram/detail/detect.hpp>
+#include <boost/histogram/detail/static_if.hpp>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <class T>
+auto make_default(const T& t) {
+ return static_if<has_allocator<T>>([](const auto& t) { return T(t.get_allocator()); },
+ [](const auto&) { return T{}; }, t);
+}
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/meta.hpp b/boost/histogram/detail/meta.hpp
deleted file mode 100644
index 0a5c5ea0ff..0000000000
--- a/boost/histogram/detail/meta.hpp
+++ /dev/null
@@ -1,436 +0,0 @@
-// Copyright 2015-2018 Hans Dembinski
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt
-// or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_HISTOGRAM_DETAIL_META_HPP
-#define BOOST_HISTOGRAM_DETAIL_META_HPP
-
-/* Most of the histogram code is generic and works for any number of axes. Buffers with a
- * fixed maximum capacity are used in some places, which have a size equal to the rank of
- * a histogram. The buffers are statically allocated to improve performance, which means
- * that they need a preset maximum capacity. 32 seems like a safe upper limit for the rank
- * (you can nevertheless increase it here if necessary): the simplest non-trivial axis has
- * 2 bins; even if counters are used which need only a byte of storage per bin, this still
- * corresponds to 4 GB of storage.
- */
-#ifndef BOOST_HISTOGRAM_DETAIL_AXES_LIMIT
-#define BOOST_HISTOGRAM_DETAIL_AXES_LIMIT 32
-#endif
-
-#include <boost/config/workaround.hpp>
-#if BOOST_WORKAROUND(BOOST_GCC, >= 60000)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wnoexcept-type"
-#endif
-#include <boost/callable_traits/args.hpp>
-#include <boost/callable_traits/return_type.hpp>
-#if BOOST_WORKAROUND(BOOST_GCC, >= 60000)
-#pragma GCC diagnostic pop
-#endif
-#include <array>
-#include <boost/histogram/fwd.hpp>
-#include <boost/mp11/algorithm.hpp>
-#include <boost/mp11/function.hpp>
-#include <boost/mp11/integer_sequence.hpp>
-#include <boost/mp11/list.hpp>
-#include <boost/mp11/utility.hpp>
-#include <functional>
-#include <iterator>
-#include <limits>
-#include <tuple>
-#include <type_traits>
-
-namespace boost {
-namespace histogram {
-namespace detail {
-
-template <class T>
-using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
-
-template <class T, class U>
-using convert_integer = mp11::mp_if<std::is_integral<remove_cvref_t<T>>, U, T>;
-
-// to be replaced by official version from mp11
-template <class E, template <class...> class F, class... Ts>
-using mp_eval_or = mp11::mp_eval_if_c<!(mp11::mp_valid<F, Ts...>::value), E, F, Ts...>;
-
-template <class T1, class T2>
-using copy_qualifiers = mp11::mp_if<
- std::is_rvalue_reference<T1>, T2&&,
- mp11::mp_if<std::is_lvalue_reference<T1>,
- mp11::mp_if<std::is_const<typename std::remove_reference<T1>::type>,
- const T2&, T2&>,
- mp11::mp_if<std::is_const<T1>, const T2, T2>>>;
-
-template <class L>
-using mp_last = mp11::mp_at_c<L, (mp11::mp_size<L>::value - 1)>;
-
-template <class T, class Args = boost::callable_traits::args_t<T>>
-using args_type =
- mp11::mp_if<std::is_member_function_pointer<T>, mp11::mp_pop_front<Args>, Args>;
-
-template <class T, std::size_t N = 0>
-using arg_type = typename mp11::mp_at_c<args_type<T>, N>;
-
-template <class T>
-using return_type = typename boost::callable_traits::return_type<T>::type;
-
-template <class F, class V,
- class T = copy_qualifiers<V, mp11::mp_first<remove_cvref_t<V>>>>
-using visitor_return_type = decltype(std::declval<F>()(std::declval<T>()));
-
-template <bool B, typename T, typename F, typename... Ts>
-constexpr decltype(auto) static_if_c(T&& t, F&& f, Ts&&... ts) {
- return std::get<(B ? 0 : 1)>(std::forward_as_tuple(
- std::forward<T>(t), std::forward<F>(f)))(std::forward<Ts>(ts)...);
-}
-
-template <typename B, typename... Ts>
-constexpr decltype(auto) static_if(Ts&&... ts) {
- return static_if_c<B::value>(std::forward<Ts>(ts)...);
-}
-
-template <typename T>
-constexpr T lowest() {
- return std::numeric_limits<T>::lowest();
-}
-
-template <>
-constexpr double lowest() {
- return -std::numeric_limits<double>::infinity();
-}
-
-template <>
-constexpr float lowest() {
- return -std::numeric_limits<float>::infinity();
-}
-
-template <typename T>
-constexpr T highest() {
- return std::numeric_limits<T>::max();
-}
-
-template <>
-constexpr double highest() {
- return std::numeric_limits<double>::infinity();
-}
-
-template <>
-constexpr float highest() {
- return std::numeric_limits<float>::infinity();
-}
-
-template <std::size_t I, class T, std::size_t... N>
-decltype(auto) tuple_slice_impl(T&& t, mp11::index_sequence<N...>) {
- return std::forward_as_tuple(std::get<(N + I)>(std::forward<T>(t))...);
-}
-
-template <std::size_t I, std::size_t N, class T>
-decltype(auto) tuple_slice(T&& t) {
- static_assert(I + N <= mp11::mp_size<remove_cvref_t<T>>::value,
- "I and N must describe a slice");
- return tuple_slice_impl<I>(std::forward<T>(t), mp11::make_index_sequence<N>{});
-}
-
-#define BOOST_HISTOGRAM_DETECT(name, cond) \
- template <class T, class = decltype(cond)> \
- struct name##_impl {}; \
- template <class T> \
- using name = typename mp11::mp_valid<name##_impl, T>
-
-#define BOOST_HISTOGRAM_DETECT_BINARY(name, cond) \
- template <class T, class U, class = decltype(cond)> \
- struct name##_impl {}; \
- template <class T, class U = T> \
- using name = typename mp11::mp_valid<name##_impl, T, U>
-
-BOOST_HISTOGRAM_DETECT(has_method_metadata, (std::declval<T&>().metadata()));
-
-// resize has two overloads, trying to get pmf in this case always fails
-BOOST_HISTOGRAM_DETECT(has_method_resize, (std::declval<T&>().resize(0)));
-
-BOOST_HISTOGRAM_DETECT(has_method_size, &T::size);
-
-BOOST_HISTOGRAM_DETECT(has_method_clear, &T::clear);
-
-BOOST_HISTOGRAM_DETECT(has_method_lower, &T::lower);
-
-BOOST_HISTOGRAM_DETECT(has_method_value, &T::value);
-
-BOOST_HISTOGRAM_DETECT(has_method_update, (&T::update));
-
-BOOST_HISTOGRAM_DETECT(has_method_reset, (std::declval<T>().reset(0)));
-
-template <typename T>
-using get_value_method_return_type_impl = decltype(std::declval<T&>().value(0));
-
-template <typename T, typename R>
-using has_method_value_with_convertible_return_type =
- typename std::is_convertible<mp_eval_or<void, get_value_method_return_type_impl, T>,
- R>::type;
-
-BOOST_HISTOGRAM_DETECT(has_method_options, (&T::options));
-
-BOOST_HISTOGRAM_DETECT(has_allocator, &T::get_allocator);
-
-BOOST_HISTOGRAM_DETECT(is_indexable, (std::declval<T&>()[0]));
-
-BOOST_HISTOGRAM_DETECT(is_transform, (&T::forward, &T::inverse));
-
-BOOST_HISTOGRAM_DETECT(is_indexable_container,
- (std::declval<T>()[0], &T::size, std::begin(std::declval<T>()),
- std::end(std::declval<T>())));
-
-BOOST_HISTOGRAM_DETECT(is_vector_like,
- (std::declval<T>()[0], &T::size, std::declval<T>().resize(0),
- std::begin(std::declval<T>()), std::end(std::declval<T>())));
-
-BOOST_HISTOGRAM_DETECT(is_array_like,
- (std::declval<T>()[0], &T::size, std::tuple_size<T>::value,
- std::begin(std::declval<T>()), std::end(std::declval<T>())));
-
-BOOST_HISTOGRAM_DETECT(is_map_like,
- (std::declval<typename T::key_type>(),
- std::declval<typename T::mapped_type>(),
- std::begin(std::declval<T>()), std::end(std::declval<T>())));
-
-// ok: is_axis is false for axis::variant, operator() is templated
-BOOST_HISTOGRAM_DETECT(is_axis, (&T::size, &T::index));
-
-BOOST_HISTOGRAM_DETECT(is_iterable,
- (std::begin(std::declval<T&>()), std::end(std::declval<T&>())));
-
-BOOST_HISTOGRAM_DETECT(is_iterator,
- (typename std::iterator_traits<T>::iterator_category()));
-
-BOOST_HISTOGRAM_DETECT(is_streamable,
- (std::declval<std::ostream&>() << std::declval<T&>()));
-
-BOOST_HISTOGRAM_DETECT(is_incrementable, (++std::declval<T&>()));
-
-BOOST_HISTOGRAM_DETECT(has_operator_preincrement, (++std::declval<T&>()));
-
-BOOST_HISTOGRAM_DETECT_BINARY(has_operator_equal,
- (std::declval<const T&>() == std::declval<const U&>()));
-
-BOOST_HISTOGRAM_DETECT_BINARY(has_operator_radd,
- (std::declval<T&>() += std::declval<U&>()));
-
-BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rsub,
- (std::declval<T&>() -= std::declval<U&>()));
-
-BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rmul,
- (std::declval<T&>() *= std::declval<U&>()));
-
-BOOST_HISTOGRAM_DETECT_BINARY(has_operator_rdiv,
- (std::declval<T&>() /= std::declval<U&>()));
-
-template <typename T>
-using is_storage =
- mp11::mp_bool<(is_indexable_container<T>::value && has_method_reset<T>::value)>;
-
-template <typename T>
-struct is_tuple_impl : std::false_type {};
-
-template <typename... Ts>
-struct is_tuple_impl<std::tuple<Ts...>> : std::true_type {};
-
-template <typename T>
-using is_tuple = typename is_tuple_impl<T>::type;
-
-template <typename T>
-struct is_axis_variant_impl : std::false_type {};
-
-template <typename... Ts>
-struct is_axis_variant_impl<axis::variant<Ts...>> : std::true_type {};
-
-template <typename T>
-using is_axis_variant = typename is_axis_variant_impl<T>::type;
-
-template <typename T>
-using is_any_axis = mp11::mp_or<is_axis<T>, is_axis_variant<T>>;
-
-template <typename T>
-using is_sequence_of_axis = mp11::mp_and<is_iterable<T>, is_axis<mp11::mp_first<T>>>;
-
-template <typename T>
-using is_sequence_of_axis_variant =
- mp11::mp_and<is_iterable<T>, is_axis_variant<mp11::mp_first<T>>>;
-
-template <typename T>
-using is_sequence_of_any_axis =
- mp11::mp_and<is_iterable<T>, is_any_axis<mp11::mp_first<T>>>;
-
-template <typename T>
-struct is_weight_impl : std::false_type {};
-
-template <typename T>
-struct is_weight_impl<weight_type<T>> : std::true_type {};
-
-template <typename T>
-using is_weight = is_weight_impl<remove_cvref_t<T>>;
-
-template <typename T>
-struct is_sample_impl : std::false_type {};
-
-template <typename T>
-struct is_sample_impl<sample_type<T>> : std::true_type {};
-
-template <typename T>
-using is_sample = is_sample_impl<remove_cvref_t<T>>;
-
-// poor-mans concept checks
-template <class T, class = std::enable_if_t<is_iterator<remove_cvref_t<T>>::value>>
-struct requires_iterator {};
-
-template <class T, class = std::enable_if_t<is_iterable<remove_cvref_t<T>>::value>>
-struct requires_iterable {};
-
-template <class T, class = std::enable_if_t<is_axis<remove_cvref_t<T>>::value>>
-struct requires_axis {};
-
-template <class T, class = std::enable_if_t<is_any_axis<remove_cvref_t<T>>::value>>
-struct requires_any_axis {};
-
-template <class T,
- class = std::enable_if_t<is_sequence_of_axis<remove_cvref_t<T>>::value>>
-struct requires_sequence_of_axis {};
-
-template <class T,
- class = std::enable_if_t<is_sequence_of_axis_variant<remove_cvref_t<T>>::value>>
-struct requires_sequence_of_axis_variant {};
-
-template <class T,
- class = std::enable_if_t<is_sequence_of_any_axis<remove_cvref_t<T>>::value>>
-struct requires_sequence_of_any_axis {};
-
-template <class T,
- class = std::enable_if_t<is_any_axis<mp11::mp_first<remove_cvref_t<T>>>::value>>
-struct requires_axes {};
-
-template <class T, class U, class = std::enable_if_t<std::is_convertible<T, U>::value>>
-struct requires_convertible {};
-
-template <class T>
-auto make_default(const T& t) {
- return static_if<has_allocator<T>>([](const auto& t) { return T(t.get_allocator()); },
- [](const auto&) { return T(); }, t);
-}
-
-template <class T>
-using tuple_size_t = typename std::tuple_size<T>::type;
-
-template <class T>
-constexpr std::size_t get_size_impl(std::true_type, const T&) noexcept {
- return std::tuple_size<T>::value;
-}
-
-template <class T>
-std::size_t get_size_impl(std::false_type, const T& t) noexcept {
- using std::begin;
- using std::end;
- return static_cast<std::size_t>(std::distance(begin(t), end(t)));
-}
-
-template <class T>
-std::size_t get_size(const T& t) noexcept {
- return get_size_impl(mp11::mp_valid<tuple_size_t, T>(), t);
-}
-
-template <class T>
-using buffer_size =
- mp_eval_or<std::integral_constant<std::size_t, BOOST_HISTOGRAM_DETAIL_AXES_LIMIT>,
- tuple_size_t, T>;
-
-template <class T, std::size_t N>
-class sub_array : public std::array<T, N> {
-public:
- explicit sub_array(std::size_t s) : size_(s) {}
- sub_array(std::size_t s, T value) : size_(s) { std::array<T, N>::fill(value); }
-
- // need to override both versions of std::array
- auto end() noexcept { return std::array<T, N>::begin() + size_; }
- auto end() const noexcept { return std::array<T, N>::begin() + size_; }
-
- auto size() const noexcept { return size_; }
-
-private:
- std::size_t size_ = N;
-};
-
-template <class U, class T>
-using stack_buffer = sub_array<U, buffer_size<T>::value>;
-
-template <class U, class T, class... Ts>
-auto make_stack_buffer(const T& t, Ts&&... ts) {
- return stack_buffer<U, T>(get_size(t), std::forward<Ts>(ts)...);
-}
-
-template <class T>
-constexpr bool relaxed_equal(const T& a, const T& b) noexcept {
- return static_if<has_operator_equal<T>>(
- [](const auto& a, const auto& b) { return a == b; },
- [](const auto&, const auto&) { return true; }, a, b);
-}
-
-template <class T>
-using get_scale_type_helper = typename T::value_type;
-
-template <class T>
-using get_scale_type = mp_eval_or<T, detail::get_scale_type_helper, T>;
-
-struct one_unit {};
-
-template <class T>
-T operator*(T&& t, const one_unit&) {
- return std::forward<T>(t);
-}
-
-template <class T>
-T operator/(T&& t, const one_unit&) {
- return std::forward<T>(t);
-}
-
-template <class T>
-using get_unit_type_helper = typename T::unit_type;
-
-template <class T>
-using get_unit_type = mp_eval_or<one_unit, detail::get_unit_type_helper, T>;
-
-template <class T, class R = get_scale_type<T>>
-R get_scale(const T& t) {
- return t / get_unit_type<T>();
-}
-
-template <class T, class Default>
-using replace_default = mp11::mp_if<std::is_same<T, use_default>, Default, T>;
-
-template <class T, class U>
-using is_convertible_helper =
- mp11::mp_apply<mp11::mp_all, mp11::mp_transform<std::is_convertible, T, U>>;
-
-template <class T, class U>
-using is_convertible = mp_eval_or<std::false_type, is_convertible_helper, T, U>;
-
-template <class T>
-auto make_unsigned_impl(std::true_type, const T t) noexcept {
- return static_cast<typename std::make_unsigned<T>::type>(t);
-}
-
-template <class T>
-auto make_unsigned_impl(std::false_type, const T t) noexcept {
- return t;
-}
-
-template <class T>
-auto make_unsigned(const T t) noexcept {
- return make_unsigned_impl(std::is_integral<T>{}, t);
-}
-
-} // namespace detail
-} // namespace histogram
-} // namespace boost
-
-#endif
diff --git a/boost/histogram/detail/noop_mutex.hpp b/boost/histogram/detail/noop_mutex.hpp
new file mode 100644
index 0000000000..543284d099
--- /dev/null
+++ b/boost/histogram/detail/noop_mutex.hpp
@@ -0,0 +1,24 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_NOOP_MUTEX_HPP
+#define BOOST_HISTOGRAM_DETAIL_NOOP_MUTEX_HPP
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+struct noop_mutex {
+ bool try_lock() noexcept { return true; }
+ void lock() noexcept {}
+ void unlock() noexcept {}
+};
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/operators.hpp b/boost/histogram/detail/operators.hpp
new file mode 100644
index 0000000000..b781c495ad
--- /dev/null
+++ b/boost/histogram/detail/operators.hpp
@@ -0,0 +1,135 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_OPERATORS_HPP
+#define BOOST_HISTOGRAM_DETAIL_OPERATORS_HPP
+
+#include <boost/histogram/detail/detect.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <class T, class U>
+using if_not_same_and_has_eq =
+ std::enable_if_t<(!std::is_same<T, U>::value && has_method_eq<T, U>::value), bool>;
+
+// totally_ordered is for types with a <= b == !(a > b) [floats with NaN violate this]
+// Derived must implement <,== for symmetric form and <,>,== for non-symmetric.
+
+// partially_ordered is for types with a <= b == a < b || a == b [for floats with NaN]
+// Derived must implement <,== for the symmetric form and <,>,== for non-symmetric.
+
+template <class T, class U>
+struct mirrored {
+ friend bool operator<(const U& a, const T& b) noexcept { return b > a; }
+ friend bool operator>(const U& a, const T& b) noexcept { return b < a; }
+ friend bool operator==(const U& a, const T& b) noexcept { return b == a; }
+ friend bool operator<=(const U& a, const T& b) noexcept { return b >= a; }
+ friend bool operator>=(const U& a, const T& b) noexcept { return b <= a; }
+ friend bool operator!=(const U& a, const T& b) noexcept { return b != a; }
+};
+
+template <class T>
+struct mirrored<T, void> {
+ template <class U>
+ friend if_not_same_and_has_eq<T, U> operator<(const U& a, const T& b) noexcept {
+ return b > a;
+ }
+ template <class U>
+ friend if_not_same_and_has_eq<T, U> operator>(const U& a, const T& b) noexcept {
+ return b < a;
+ }
+ template <class U>
+ friend if_not_same_and_has_eq<T, U> operator==(const U& a, const T& b) noexcept {
+ return b == a;
+ }
+ template <class U>
+ friend if_not_same_and_has_eq<T, U> operator<=(const U& a, const T& b) noexcept {
+ return b >= a;
+ }
+ template <class U>
+ friend if_not_same_and_has_eq<T, U> operator>=(const U& a, const T& b) noexcept {
+ return b <= a;
+ }
+ template <class U>
+ friend if_not_same_and_has_eq<T, U> operator!=(const U& a, const T& b) noexcept {
+ return b != a;
+ }
+};
+
+template <class T>
+struct mirrored<T, T> {
+ friend bool operator>(const T& a, const T& b) noexcept { return b.operator<(a); }
+};
+
+template <class T, class U>
+struct equality {
+ friend bool operator!=(const T& a, const U& b) noexcept { return !a.operator==(b); }
+};
+
+template <class T>
+struct equality<T, void> {
+ template <class U>
+ friend if_not_same_and_has_eq<T, U> operator!=(const T& a, const U& b) noexcept {
+ return !(a == b);
+ }
+};
+
+template <class T, class U>
+struct totally_ordered_impl : equality<T, U>, mirrored<T, U> {
+ friend bool operator<=(const T& a, const U& b) noexcept { return !(a > b); }
+ friend bool operator>=(const T& a, const U& b) noexcept { return !(a < b); }
+};
+
+template <class T>
+struct totally_ordered_impl<T, void> : equality<T, void>, mirrored<T, void> {
+ template <class U>
+ friend if_not_same_and_has_eq<T, U> operator<=(const T& a, const U& b) noexcept {
+ return !(a > b);
+ }
+ template <class U>
+ friend if_not_same_and_has_eq<T, U> operator>=(const T& a, const U& b) noexcept {
+ return !(a < b);
+ }
+};
+
+template <class T, class... Ts>
+using totally_ordered = mp11::mp_rename<
+ mp11::mp_product<totally_ordered_impl, mp11::mp_list<T>, mp11::mp_list<Ts...> >,
+ mp11::mp_inherit>;
+
+template <class T, class U>
+struct partially_ordered_impl : equality<T, U>, mirrored<T, U> {
+ friend bool operator<=(const T& a, const U& b) noexcept { return a < b || a == b; }
+ friend bool operator>=(const T& a, const U& b) noexcept { return a > b || a == b; }
+};
+
+template <class T>
+struct partially_ordered_impl<T, void> : equality<T, void>, mirrored<T, void> {
+ template <class U>
+ friend if_not_same_and_has_eq<T, U> operator<=(const T& a, const U& b) noexcept {
+ return a < b || a == b;
+ }
+ template <class U>
+ friend if_not_same_and_has_eq<T, U> operator>=(const T& a, const U& b) noexcept {
+ return a > b || a == b;
+ }
+};
+
+template <class T, class... Ts>
+using partially_ordered = mp11::mp_rename<
+ mp11::mp_product<partially_ordered_impl, mp11::mp_list<T>, mp11::mp_list<Ts...> >,
+ mp11::mp_inherit>;
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif // BOOST_HISTOGRAM_DETAIL_OPERATORS_HPP
diff --git a/boost/histogram/detail/relaxed_equal.hpp b/boost/histogram/detail/relaxed_equal.hpp
new file mode 100644
index 0000000000..123a05a20b
--- /dev/null
+++ b/boost/histogram/detail/relaxed_equal.hpp
@@ -0,0 +1,28 @@
+// Copyright 2015-2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_RELAXED_EQUAL_HPP
+#define BOOST_HISTOGRAM_DETAIL_RELAXED_EQUAL_HPP
+
+#include <boost/histogram/detail/detect.hpp>
+#include <boost/histogram/detail/static_if.hpp>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <class T>
+constexpr bool relaxed_equal(const T& a, const T& b) noexcept {
+ return static_if<has_operator_equal<T>>(
+ [](const auto& a, const auto& b) { return a == b; },
+ [](const auto&, const auto&) { return true; }, a, b);
+}
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/replace_default.hpp b/boost/histogram/detail/replace_default.hpp
new file mode 100644
index 0000000000..16c4c071c4
--- /dev/null
+++ b/boost/histogram/detail/replace_default.hpp
@@ -0,0 +1,25 @@
+// Copyright 2015-2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_REPLACE_DEFAULT_HPP
+#define BOOST_HISTOGRAM_DETAIL_REPLACE_DEFAULT_HPP
+
+#include <boost/core/use_default.hpp>
+#include <type_traits>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <class T, class Default>
+using replace_default =
+ std::conditional_t<std::is_same<T, boost::use_default>::value, Default, T>;
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/safe_comparison.hpp b/boost/histogram/detail/safe_comparison.hpp
new file mode 100644
index 0000000000..3ac793ba44
--- /dev/null
+++ b/boost/histogram/detail/safe_comparison.hpp
@@ -0,0 +1,87 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_SAFE_COMPARISON_HPP
+#define BOOST_HISTOGRAM_DETAIL_SAFE_COMPARISON_HPP
+
+#include <boost/mp11/utility.hpp>
+#include <boost/type.hpp>
+#include <type_traits>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <class T>
+auto make_unsigned(const T& t) noexcept {
+ static_assert(std::is_integral<T>::value, "");
+ return static_cast<std::make_unsigned_t<T>>(t);
+}
+
+template <class T>
+using number_category =
+ mp11::mp_if<std::is_integral<T>,
+ mp11::mp_if<std::is_signed<T>, type<int>, type<unsigned>>, type<void>>;
+
+// version of std::equal_to<> which handles signed and unsigned integers correctly
+struct safe_equal {
+ template <class T, class U>
+ bool operator()(const T& t, const U& u) const noexcept {
+ return impl(number_category<T>{}, number_category<U>{}, t, u);
+ }
+
+ template <class C1, class C2, class T, class U>
+ bool impl(C1, C2, const T& t, const U& u) const noexcept {
+ return t == u;
+ }
+
+ template <class T, class U>
+ bool impl(type<int>, type<unsigned>, const T& t, const U& u) const noexcept {
+ return t >= 0 && make_unsigned(t) == u;
+ }
+
+ template <class T, class U>
+ bool impl(type<unsigned>, type<int>, const T& t, const U& u) const noexcept {
+ return impl(type<int>{}, type<unsigned>{}, u, t);
+ }
+};
+
+// version of std::less<> which handles signed and unsigned integers correctly
+struct safe_less {
+ template <class T, class U>
+ bool operator()(const T& t, const U& u) const noexcept {
+ return impl(number_category<T>{}, number_category<U>{}, t, u);
+ }
+
+ template <class C1, class C2, class T, class U>
+ bool impl(C1, C2, const T& t, const U& u) const noexcept {
+ return t < u;
+ }
+
+ template <class T, class U>
+ bool impl(type<int>, type<unsigned>, const T& t, const U& u) const noexcept {
+ return t < 0 || make_unsigned(t) < u;
+ }
+
+ template <class T, class U>
+ bool impl(type<unsigned>, type<int>, const T& t, const U& u) const noexcept {
+ return 0 < u && t < make_unsigned(u);
+ }
+};
+
+// version of std::greater<> which handles signed and unsigned integers correctly
+struct safe_greater {
+ template <class T, class U>
+ bool operator()(const T& t, const U& u) const noexcept {
+ return safe_less()(u, t);
+ }
+};
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/static_if.hpp b/boost/histogram/detail/static_if.hpp
new file mode 100644
index 0000000000..0f12a02229
--- /dev/null
+++ b/boost/histogram/detail/static_if.hpp
@@ -0,0 +1,46 @@
+// Copyright 2018-2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_STATIC_IF_HPP
+#define BOOST_HISTOGRAM_DETAIL_STATIC_IF_HPP
+
+#include <type_traits>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <class T, class F, class... Args>
+constexpr decltype(auto) static_if_impl(
+ std::true_type, T&& t, F&&,
+ Args&&... args) noexcept(noexcept(std::declval<T>()(std::declval<Args>()...))) {
+ return std::forward<T>(t)(std::forward<Args>(args)...);
+}
+
+template <class T, class F, class... Args>
+constexpr decltype(auto) static_if_impl(
+ std::false_type, T&&, F&& f,
+ Args&&... args) noexcept(noexcept(std::declval<F>()(std::declval<Args>()...))) {
+ return std::forward<F>(f)(std::forward<Args>(args)...);
+}
+
+template <bool B, class... Ts>
+constexpr decltype(auto) static_if_c(Ts&&... ts) noexcept(
+ noexcept(static_if_impl(std::integral_constant<bool, B>{}, std::declval<Ts>()...))) {
+ return static_if_impl(std::integral_constant<bool, B>{}, std::forward<Ts>(ts)...);
+}
+
+template <class Bool, class... Ts>
+constexpr decltype(auto) static_if(Ts&&... ts) noexcept(
+ noexcept(static_if_impl(Bool{}, std::declval<Ts>()...))) {
+ return static_if_impl(Bool{}, std::forward<Ts>(ts)...);
+}
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/try_cast.hpp b/boost/histogram/detail/try_cast.hpp
new file mode 100644
index 0000000000..249f4e0317
--- /dev/null
+++ b/boost/histogram/detail/try_cast.hpp
@@ -0,0 +1,49 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_TRY_CAST_HPP
+#define BOOST_HISTOGRAM_DETAIL_TRY_CAST_HPP
+
+#include <boost/config.hpp>
+#include <boost/core/demangle.hpp>
+#include <boost/histogram/detail/cat.hpp>
+#include <boost/histogram/detail/type_name.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/throw_exception.hpp>
+#include <stdexcept>
+#include <type_traits>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+template <class T, class E, class U>
+BOOST_NORETURN T try_cast_impl(mp11::mp_int<0>, U&&) {
+ BOOST_THROW_EXCEPTION(E(cat("cannot cast ", type_name<T>(), " to ", type_name<U>())));
+}
+
+template <class T, class E, class U>
+T try_cast_impl(mp11::mp_int<1>, U&& u) noexcept {
+ return static_cast<T>(u);
+}
+
+template <class T, class E, class U>
+decltype(auto) try_cast_impl(mp11::mp_int<2>, U&& u) noexcept {
+ return std::forward<U>(u);
+}
+
+// cast fails at runtime with exception E instead of compile-time, T must be a value
+template <class T, class E, class U>
+decltype(auto) try_cast(U&& u) noexcept(std::is_convertible<U, T>::value) {
+ return try_cast_impl<T, E>(mp11::mp_int<(std::is_convertible<U, T>::value +
+ std::is_same<T, std::decay_t<U>>::value)>{},
+ std::forward<U>(u));
+}
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/tuple_slice.hpp b/boost/histogram/detail/tuple_slice.hpp
new file mode 100644
index 0000000000..a48a10598c
--- /dev/null
+++ b/boost/histogram/detail/tuple_slice.hpp
@@ -0,0 +1,34 @@
+// Copyright 2015-2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_TUPLE_SLICE_HPP
+#define BOOST_HISTOGRAM_DETAIL_TUPLE_SLICE_HPP
+
+#include <boost/mp11/integer_sequence.hpp>
+#include <tuple>
+#include <type_traits>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <std::size_t I, class T, std::size_t... K>
+decltype(auto) tuple_slice_impl(T&& t, mp11::index_sequence<K...>) {
+ return std::forward_as_tuple(std::get<(I + K)>(std::forward<T>(t))...);
+}
+
+template <std::size_t I, std::size_t N, class Tuple>
+decltype(auto) tuple_slice(Tuple&& t) {
+ constexpr auto S = std::tuple_size<std::decay_t<Tuple>>::value;
+ static_assert(I + N <= S, "I, N must be a valid subset");
+ return tuple_slice_impl<I>(std::forward<Tuple>(t), mp11::make_index_sequence<N>{});
+}
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/detail/type_name.hpp b/boost/histogram/detail/type_name.hpp
new file mode 100644
index 0000000000..25950bcaba
--- /dev/null
+++ b/boost/histogram/detail/type_name.hpp
@@ -0,0 +1,51 @@
+// Copyright 2019 Hans Dembinski
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_HISTOGRAM_DETAIL_TYPE_NAME_HPP
+#define BOOST_HISTOGRAM_DETAIL_TYPE_NAME_HPP
+
+#include <boost/core/typeinfo.hpp>
+#include <boost/type.hpp>
+#include <sstream>
+#include <string>
+
+namespace boost {
+namespace histogram {
+namespace detail {
+
+template <class T>
+std::ostream& type_name_impl(std::ostream& os, boost::type<T>) {
+ os << boost::core::demangled_name(BOOST_CORE_TYPEID(T));
+ return os;
+}
+
+template <class T>
+std::ostream& type_name_impl(std::ostream& os, boost::type<const T>) {
+ return type_name_impl(os, boost::type<T>{}) << " const";
+}
+
+template <class T>
+std::ostream& type_name_impl(std::ostream& os, boost::type<T&>) {
+ return type_name_impl(os, boost::type<T>{}) << "&";
+}
+
+template <class T>
+std::ostream& type_name_impl(std::ostream& os, boost::type<T&&>) {
+ return type_name_impl(os, boost::type<T>{}) << "&&";
+}
+
+template <class T>
+std::string type_name() {
+ std::ostringstream os;
+ type_name_impl(os, boost::type<T>{});
+ return os.str();
+}
+
+} // namespace detail
+} // namespace histogram
+} // namespace boost
+
+#endif
diff --git a/boost/histogram/fwd.hpp b/boost/histogram/fwd.hpp
index 60f372e903..cc042bb7eb 100644
--- a/boost/histogram/fwd.hpp
+++ b/boost/histogram/fwd.hpp
@@ -1,4 +1,4 @@
-// Copyright 2015-2017 Hans Dembinski
+// Copyright 2015-2019 Hans Dembinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
@@ -13,8 +13,7 @@
*/
#include <boost/core/use_default.hpp>
-#include <boost/histogram/detail/attribute.hpp> // BOOST_HISTOGRAM_DETAIL_NODISCARD
-#include <string>
+#include <boost/histogram/detail/attribute.hpp> // BOOST_HISTOGRAM_NODISCARD
#include <vector>
namespace boost {
@@ -82,6 +81,14 @@ template <class Value = double>
class mean;
template <class Value = double>
class weighted_mean;
+
+template <class T>
+class thread_safe;
+
+template <class T>
+struct is_thread_safe : std::false_type {};
+template <class T>
+struct is_thread_safe<thread_safe<T>> : std::true_type {};
} // namespace accumulators
struct unsafe_access;
@@ -94,26 +101,26 @@ class storage_adaptor;
#endif // BOOST_HISTOGRAM_DOXYGEN_INVOKED
-/// Vector-like storage for fast zero-overhead access to cells
+/// Vector-like storage for fast zero-overhead access to cells.
template <class T, class A = std::allocator<T>>
using dense_storage = storage_adaptor<std::vector<T, A>>;
/// Default storage, optimized for unweighted histograms
using default_storage = unlimited_storage<>;
-/// Dense storage which tracks sums of weights and a variance estimate
+/// Dense storage which tracks sums of weights and a variance estimate.
using weight_storage = dense_storage<accumulators::weighted_sum<>>;
-/// Dense storage which tracks means of samples in each cell
+/// Dense storage which tracks means of samples in each cell.
using profile_storage = dense_storage<accumulators::mean<>>;
-/// Dense storage which tracks means of weighted samples in each cell
+/// Dense storage which tracks means of weighted samples in each cell.
using weighted_profile_storage = dense_storage<accumulators::weighted_mean<>>;
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
template <class Axes, class Storage = default_storage>
-class BOOST_HISTOGRAM_DETAIL_NODISCARD histogram;
+class BOOST_HISTOGRAM_NODISCARD histogram;
#endif
} // namespace histogram
diff --git a/boost/histogram/histogram.hpp b/boost/histogram/histogram.hpp
index 2cb34feca1..75bc0df49f 100644
--- a/boost/histogram/histogram.hpp
+++ b/boost/histogram/histogram.hpp
@@ -9,15 +9,21 @@
#include <boost/histogram/detail/axes.hpp>
#include <boost/histogram/detail/common_type.hpp>
+#include <boost/histogram/detail/compressed_pair.hpp>
#include <boost/histogram/detail/linearize.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/noop_mutex.hpp>
+#include <boost/histogram/detail/static_if.hpp>
#include <boost/histogram/fwd.hpp>
+#include <boost/histogram/storage_adaptor.hpp>
+#include <boost/histogram/unsafe_access.hpp>
#include <boost/mp11/list.hpp>
#include <boost/throw_exception.hpp>
+#include <mutex>
#include <stdexcept>
#include <tuple>
#include <type_traits>
#include <utility>
+#include <vector>
namespace boost {
namespace histogram {
@@ -44,7 +50,7 @@ template <class Axes, class Storage>
class histogram {
public:
static_assert(mp11::mp_size<Axes>::value > 0, "at least one axis required");
- static_assert(std::is_same<detail::remove_cvref_t<Storage>, Storage>::value,
+ static_assert(std::is_same<std::decay_t<Storage>, Storage>::value,
"Storage may not be a reference or const or volatile");
public:
@@ -56,53 +62,69 @@ public:
using const_iterator = typename storage_type::const_iterator;
histogram() = default;
- histogram(const histogram& rhs) = default;
- histogram(histogram&& rhs) = default;
- histogram& operator=(const histogram& rhs) = default;
- histogram& operator=(histogram&& rhs) = default;
+ histogram(const histogram& rhs)
+ : axes_(rhs.axes_), storage_and_mutex_(rhs.storage_and_mutex_.first()) {}
+ histogram(histogram&& rhs)
+ : axes_(std::move(rhs.axes_))
+ , storage_and_mutex_(std::move(rhs.storage_and_mutex_.first())) {}
+ histogram& operator=(histogram&& rhs) {
+ if (this != &rhs) {
+ axes_ = std::move(rhs.axes_);
+ storage_and_mutex_.first() = std::move(rhs.storage_and_mutex_.first());
+ }
+ return *this;
+ }
+ histogram& operator=(const histogram& rhs) {
+ if (this != &rhs) {
+ axes_ = rhs.axes_;
+ storage_and_mutex_.first() = rhs.storage_and_mutex_.first();
+ }
+ return *this;
+ }
template <class A, class S>
- explicit histogram(histogram<A, S>&& rhs) : storage_(std::move(rhs.storage_)) {
- detail::axes_assign(axes_, rhs.axes_);
+ explicit histogram(histogram<A, S>&& rhs)
+ : storage_and_mutex_(std::move(unsafe_access::storage(rhs))) {
+ detail::axes_assign(axes_, std::move(unsafe_access::axes(rhs)));
}
template <class A, class S>
- explicit histogram(const histogram<A, S>& rhs) : storage_(rhs.storage_) {
- detail::axes_assign(axes_, rhs.axes_);
+ explicit histogram(const histogram<A, S>& rhs)
+ : storage_and_mutex_(unsafe_access::storage(rhs)) {
+ detail::axes_assign(axes_, unsafe_access::axes(rhs));
}
template <class A, class S>
histogram& operator=(histogram<A, S>&& rhs) {
- detail::axes_assign(axes_, std::move(rhs.axes_));
- storage_ = std::move(rhs.storage_);
+ detail::axes_assign(axes_, std::move(unsafe_access::axes(rhs)));
+ storage_and_mutex_.first() = std::move(unsafe_access::storage(rhs));
return *this;
}
template <class A, class S>
histogram& operator=(const histogram<A, S>& rhs) {
- detail::axes_assign(axes_, rhs.axes_);
- storage_ = rhs.storage_;
+ detail::axes_assign(axes_, unsafe_access::axes(rhs));
+ storage_and_mutex_.first() = unsafe_access::storage(rhs);
return *this;
}
template <class A, class S>
- histogram(A&& a, S&& s) : axes_(std::forward<A>(a)), storage_(std::forward<S>(s)) {
- storage_.reset(detail::bincount(axes_));
+ histogram(A&& a, S&& s)
+ : axes_(std::forward<A>(a)), storage_and_mutex_(std::forward<S>(s)) {
+ storage_and_mutex_.first().reset(detail::bincount(axes_));
}
template <class A, class = detail::requires_axes<A>>
explicit histogram(A&& a) : histogram(std::forward<A>(a), storage_type()) {}
/// Number of axes (dimensions).
- constexpr unsigned rank() const noexcept {
- return static_cast<unsigned>(detail::get_size(axes_));
- }
+ constexpr unsigned rank() const noexcept { return detail::axes_rank(axes_); }
/// Total number of bins (including underflow/overflow).
- std::size_t size() const noexcept { return storage_.size(); }
+ std::size_t size() const noexcept { return storage_and_mutex_.first().size(); }
/// Reset all bins to default initialized values.
- void reset() { storage_.reset(storage_.size()); }
+ void reset() { storage_and_mutex_.first().reset(size()); }
/// Get N-th axis using a compile-time number.
/// This version is more efficient than the one accepting a run-time number.
@@ -113,7 +135,7 @@ public:
}
/// Get N-th axis with run-time number.
- /// Use version that accepts a compile-time number, if possible.
+ /// Prefer the version that accepts a compile-time number, if you can use it.
decltype(auto) axis(unsigned i) const {
detail::axis_index_is_valid(axes_, i);
return detail::axis_get(axes_, i);
@@ -131,13 +153,6 @@ public:
not convertible to the value type accepted by the axis or passing the wrong number
of arguments causes a throw of `std::invalid_argument`.
- __Axis with multiple arguments__
-
- If the histogram contains an axis which accepts a `std::tuple` of arguments, the
- arguments for that axis need to passed as a `std::tuple`, for example,
- `std::make_tuple(1.2, 2.3)`. If the histogram contains only this axis and no other,
- the arguments can be passed directly.
-
__Optional weight__
An optional weight can be passed as the first or last argument
@@ -151,89 +166,101 @@ public:
[sample](boost/histogram/sample.html) helper function can pass one or more arguments to
the storage element. If samples and weights are used together, they can be passed in
any order at the beginning or end of the argument list.
+
+ __Axis with multiple arguments__
+
+ If the histogram contains an axis which accepts a `std::tuple` of arguments, the
+ arguments for that axis need to passed as a `std::tuple`, for example,
+ `std::make_tuple(1.2, 2.3)`. If the histogram contains only this axis and no other,
+ the arguments can be passed directly.
*/
template <class... Ts>
- auto operator()(const Ts&... ts) {
- return operator()(std::make_tuple(ts...));
+ iterator operator()(const Ts&... ts) {
+ return operator()(std::forward_as_tuple(ts...));
}
/// Fill histogram with values, an optional weight, and/or a sample from a `std::tuple`.
template <class... Ts>
- auto operator()(const std::tuple<Ts...>& t) {
- return detail::fill(storage_, axes_, t);
+ iterator operator()(const std::tuple<Ts...>& t) {
+ std::lock_guard<mutex_type> guard{storage_and_mutex_.second()};
+ return detail::fill(axes_, storage_and_mutex_.first(), t);
}
- /// Access cell value at integral indices.
- /**
+ /** Access cell value at integral indices.
+
You can pass indices as individual arguments, as a std::tuple of integers, or as an
interable range of integers. Passing the wrong number of arguments causes a throw of
std::invalid_argument. Passing an index which is out of bounds causes a throw of
std::out_of_range.
+
+ @param i index of first axis.
+ @param is indices of second, third, ... axes.
+ @returns reference to cell value.
*/
- template <class... Ts>
- decltype(auto) at(axis::index_type t, Ts... ts) {
- return at(std::forward_as_tuple(t, ts...));
+ template <class... Indices>
+ decltype(auto) at(axis::index_type i, Indices... is) {
+ return at(std::forward_as_tuple(i, is...));
}
/// Access cell value at integral indices (read-only).
- /// @copydoc at(axis::index_type t, Ts... ts)
- template <class... Ts>
- decltype(auto) at(axis::index_type t, Ts... ts) const {
- return at(std::forward_as_tuple(t, ts...));
+ template <class... Indices>
+ decltype(auto) at(axis::index_type i, Indices... is) const {
+ return at(std::forward_as_tuple(i, is...));
}
/// Access cell value at integral indices stored in `std::tuple`.
- /// @copydoc at(axis::index_type t, Ts... ts)
- template <typename... Ts>
- decltype(auto) at(const std::tuple<Ts...>& t) {
- const auto idx = detail::at(axes_, t);
- if (!idx) BOOST_THROW_EXCEPTION(std::out_of_range("indices out of bounds"));
- return storage_[*idx];
+ template <typename... Indices>
+ decltype(auto) at(const std::tuple<Indices...>& is) {
+ const auto idx = detail::at(axes_, is);
+ if (!idx)
+ BOOST_THROW_EXCEPTION(std::out_of_range("at least one index out of bounds"));
+ return storage_and_mutex_.first()[*idx];
}
/// Access cell value at integral indices stored in `std::tuple` (read-only).
- /// @copydoc at(axis::index_type t, Ts... ts)
- template <typename... Ts>
- decltype(auto) at(const std::tuple<Ts...>& t) const {
- const auto idx = detail::at(axes_, t);
- if (!idx) BOOST_THROW_EXCEPTION(std::out_of_range("indices out of bounds"));
- return storage_[*idx];
+ template <typename... Indices>
+ decltype(auto) at(const std::tuple<Indices...>& is) const {
+ const auto idx = detail::at(axes_, is);
+ if (!idx)
+ BOOST_THROW_EXCEPTION(std::out_of_range("at least one index out of bounds"));
+ return storage_and_mutex_.first()[*idx];
}
/// Access cell value at integral indices stored in iterable.
- /// @copydoc at(axis::index_type t, Ts... ts)
template <class Iterable, class = detail::requires_iterable<Iterable>>
- decltype(auto) at(const Iterable& c) {
- const auto idx = detail::at(axes_, c);
- if (!idx) BOOST_THROW_EXCEPTION(std::out_of_range("indices out of bounds"));
- return storage_[*idx];
+ decltype(auto) at(const Iterable& is) {
+ const auto idx = detail::at(axes_, is);
+ if (!idx)
+ BOOST_THROW_EXCEPTION(std::out_of_range("at least one index out of bounds"));
+ return storage_and_mutex_.first()[*idx];
}
/// Access cell value at integral indices stored in iterable (read-only).
- /// @copydoc at(axis::index_type t, Ts... ts)
template <class Iterable, class = detail::requires_iterable<Iterable>>
- decltype(auto) at(const Iterable& c) const {
- const auto idx = detail::at(axes_, c);
- if (!idx) BOOST_THROW_EXCEPTION(std::out_of_range("indices out of bounds"));
- return storage_[*idx];
+ decltype(auto) at(const Iterable& is) const {
+ const auto idx = detail::at(axes_, is);
+ if (!idx)
+ BOOST_THROW_EXCEPTION(std::out_of_range("at least one index out of bounds"));
+ return storage_and_mutex_.first()[*idx];
}
/// Access value at index (number for rank = 1, else `std::tuple` or iterable).
- template <class T>
- decltype(auto) operator[](const T& t) {
- return at(t);
+ template <class Indices>
+ decltype(auto) operator[](const Indices& is) {
+ return at(is);
}
- /// @copydoc operator[]
- template <class T>
- decltype(auto) operator[](const T& t) const {
- return at(t);
+ /// Access value at index (read-only).
+ template <class Indices>
+ decltype(auto) operator[](const Indices& is) const {
+ return at(is);
}
/// Equality operator, tests equality for all axes and the storage.
template <class A, class S>
bool operator==(const histogram<A, S>& rhs) const noexcept {
- return detail::axes_equal(axes_, rhs.axes_) && storage_ == rhs.storage_;
+ return detail::axes_equal(axes_, unsafe_access::axes(rhs)) &&
+ storage_and_mutex_.first() == unsafe_access::storage(rhs);
}
/// Negation of the equality operator.
@@ -243,54 +270,54 @@ public:
}
/// Add values of another histogram.
- template <class A, class S>
+ template <class A, class S,
+ class = std::enable_if_t<detail::has_operator_radd<
+ value_type, typename histogram<A, S>::value_type>::value>>
histogram& operator+=(const histogram<A, S>& rhs) {
- static_assert(detail::has_operator_radd<value_type,
- typename histogram<A, S>::value_type>::value,
- "cell value does not support adding value of right-hand-side");
- if (!detail::axes_equal(axes_, rhs.axes_))
+ if (!detail::axes_equal(axes_, unsafe_access::axes(rhs)))
BOOST_THROW_EXCEPTION(std::invalid_argument("axes of histograms differ"));
- auto rit = rhs.storage_.begin();
- std::for_each(storage_.begin(), storage_.end(), [&rit](auto&& x) { x += *rit++; });
+ auto rit = unsafe_access::storage(rhs).begin();
+ auto& s = storage_and_mutex_.first();
+ std::for_each(s.begin(), s.end(), [&rit](auto&& x) { x += *rit++; });
return *this;
}
/// Subtract values of another histogram.
- template <class A, class S>
+ template <class A, class S,
+ class = std::enable_if_t<detail::has_operator_rsub<
+ value_type, typename histogram<A, S>::value_type>::value>>
histogram& operator-=(const histogram<A, S>& rhs) {
- static_assert(detail::has_operator_rsub<value_type,
- typename histogram<A, S>::value_type>::value,
- "cell value does not support subtracting value of right-hand-side");
- if (!detail::axes_equal(axes_, rhs.axes_))
+ if (!detail::axes_equal(axes_, unsafe_access::axes(rhs)))
BOOST_THROW_EXCEPTION(std::invalid_argument("axes of histograms differ"));
- auto rit = rhs.storage_.begin();
- std::for_each(storage_.begin(), storage_.end(), [&rit](auto&& x) { x -= *rit++; });
+ auto rit = unsafe_access::storage(rhs).begin();
+ auto& s = storage_and_mutex_.first();
+ std::for_each(s.begin(), s.end(), [&rit](auto&& x) { x -= *rit++; });
return *this;
}
/// Multiply by values of another histogram.
- template <class A, class S>
+ template <class A, class S,
+ class = std::enable_if_t<detail::has_operator_rmul<
+ value_type, typename histogram<A, S>::value_type>::value>>
histogram& operator*=(const histogram<A, S>& rhs) {
- static_assert(detail::has_operator_rmul<value_type,
- typename histogram<A, S>::value_type>::value,
- "cell value does not support multiplying by value of right-hand-side");
- if (!detail::axes_equal(axes_, rhs.axes_))
+ if (!detail::axes_equal(axes_, unsafe_access::axes(rhs)))
BOOST_THROW_EXCEPTION(std::invalid_argument("axes of histograms differ"));
- auto rit = rhs.storage_.begin();
- std::for_each(storage_.begin(), storage_.end(), [&rit](auto&& x) { x *= *rit++; });
+ auto rit = unsafe_access::storage(rhs).begin();
+ auto& s = storage_and_mutex_.first();
+ std::for_each(s.begin(), s.end(), [&rit](auto&& x) { x *= *rit++; });
return *this;
}
/// Divide by values of another histogram.
- template <class A, class S>
+ template <class A, class S,
+ class = std::enable_if_t<detail::has_operator_rdiv<
+ value_type, typename histogram<A, S>::value_type>::value>>
histogram& operator/=(const histogram<A, S>& rhs) {
- static_assert(detail::has_operator_rdiv<value_type,
- typename histogram<A, S>::value_type>::value,
- "cell value does not support dividing by value of right-hand-side");
- if (!detail::axes_equal(axes_, rhs.axes_))
+ if (!detail::axes_equal(axes_, unsafe_access::axes(rhs)))
BOOST_THROW_EXCEPTION(std::invalid_argument("axes of histograms differ"));
- auto rit = rhs.storage_.begin();
- std::for_each(storage_.begin(), storage_.end(), [&rit](auto&& x) { x /= *rit++; });
+ auto rit = unsafe_access::storage(rhs).begin();
+ auto& s = storage_and_mutex_.first();
+ std::for_each(s.begin(), s.end(), [&rit](auto&& x) { x /= *rit++; });
return *this;
}
@@ -304,7 +331,7 @@ public:
[](storage_type& s, auto x) {
for (auto&& si : s) si *= x;
},
- storage_, x);
+ storage_and_mutex_.first(), x);
return *this;
}
@@ -316,67 +343,101 @@ public:
}
/// Return value iterator to the beginning of the histogram.
- iterator begin() noexcept { return storage_.begin(); }
+ iterator begin() noexcept { return storage_and_mutex_.first().begin(); }
/// Return value iterator to the end in the histogram.
- iterator end() noexcept { return storage_.end(); }
+ iterator end() noexcept { return storage_and_mutex_.first().end(); }
/// Return value iterator to the beginning of the histogram (read-only).
- const_iterator begin() const noexcept { return storage_.begin(); }
+ const_iterator begin() const noexcept { return storage_and_mutex_.first().begin(); }
/// Return value iterator to the end in the histogram (read-only).
- const_iterator end() const noexcept { return storage_.end(); }
+ const_iterator end() const noexcept { return storage_and_mutex_.first().end(); }
/// Return value iterator to the beginning of the histogram (read-only).
- const_iterator cbegin() const noexcept { return storage_.begin(); }
+ const_iterator cbegin() const noexcept { return begin(); }
/// Return value iterator to the end in the histogram (read-only).
- const_iterator cend() const noexcept { return storage_.end(); }
+ const_iterator cend() const noexcept { return end(); }
private:
axes_type axes_;
- storage_type storage_;
- template <class A, class S>
- friend class histogram;
+ using mutex_type = mp11::mp_if_c<(storage_type::has_threading_support &&
+ detail::has_growing_axis<axes_type>::value),
+ std::mutex, detail::noop_mutex>;
+
+ detail::compressed_pair<storage_type, mutex_type> storage_and_mutex_;
+
friend struct unsafe_access;
};
+/**
+ Pairwise add cells of two histograms and return histogram with the sum.
+
+ The returned histogram type is the most efficient and safest one constructible from the
+ inputs, if they are not the same type. If one histogram has a tuple axis, the result has
+ a tuple axis. The chosen storage is the one with the larger dynamic range.
+*/
template <class A1, class S1, class A2, class S2>
auto operator+(const histogram<A1, S1>& a, const histogram<A2, S2>& b) {
auto r = histogram<detail::common_axes<A1, A2>, detail::common_storage<S1, S2>>(a);
return r += b;
}
+/** Pairwise multiply cells of two histograms and return histogram with the product.
+
+ For notes on the returned histogram type, see operator+.
+*/
template <class A1, class S1, class A2, class S2>
auto operator*(const histogram<A1, S1>& a, const histogram<A2, S2>& b) {
auto r = histogram<detail::common_axes<A1, A2>, detail::common_storage<S1, S2>>(a);
return r *= b;
}
+/** Pairwise subtract cells of two histograms and return histogram with the difference.
+
+ For notes on the returned histogram type, see operator+.
+*/
template <class A1, class S1, class A2, class S2>
auto operator-(const histogram<A1, S1>& a, const histogram<A2, S2>& b) {
auto r = histogram<detail::common_axes<A1, A2>, detail::common_storage<S1, S2>>(a);
return r -= b;
}
+/** Pairwise divide cells of two histograms and return histogram with the quotient.
+
+ For notes on the returned histogram type, see operator+.
+*/
template <class A1, class S1, class A2, class S2>
auto operator/(const histogram<A1, S1>& a, const histogram<A2, S2>& b) {
auto r = histogram<detail::common_axes<A1, A2>, detail::common_storage<S1, S2>>(a);
return r /= b;
}
+/** Multiply all cells of the histogram by a number and return a new histogram.
+
+ If the original histogram has integer cells, the result has double cells.
+*/
template <class A, class S>
auto operator*(const histogram<A, S>& h, double x) {
auto r = histogram<A, detail::common_storage<S, dense_storage<double>>>(h);
return r *= x;
}
+/** Multiply all cells of the histogram by a number and return a new histogram.
+
+ If the original histogram has integer cells, the result has double cells.
+*/
template <class A, class S>
auto operator*(double x, const histogram<A, S>& h) {
return h * x;
}
+/** Divide all cells of the histogram by a number and return a new histogram.
+
+ If the original histogram has integer cells, the result has double cells.
+*/
template <class A, class S>
auto operator/(const histogram<A, S>& h, double x) {
return h * (1.0 / x);
@@ -385,29 +446,32 @@ auto operator/(const histogram<A, S>& h, double x) {
#if __cpp_deduction_guides >= 201606
template <class Axes>
-histogram(Axes&& axes)->histogram<detail::remove_cvref_t<Axes>, default_storage>;
+histogram(Axes&& axes)->histogram<std::decay_t<Axes>, default_storage>;
template <class Axes, class Storage>
histogram(Axes&& axes, Storage&& storage)
- ->histogram<detail::remove_cvref_t<Axes>, detail::remove_cvref_t<Storage>>;
+ ->histogram<std::decay_t<Axes>, std::decay_t<Storage>>;
#endif
-/// Helper function to mark argument as weight.
-/// @param t argument to be forward to the histogram.
+/** Helper function to mark argument as weight.
+
+ @param t argument to be forward to the histogram.
+*/
template <typename T>
auto weight(T&& t) noexcept {
return weight_type<T>{std::forward<T>(t)};
}
-/// Helper function to mark arguments as sample.
-/// @param ts arguments to be forwarded to the accumulator.
+/** Helper function to mark arguments as sample.
+
+ @param ts arguments to be forwarded to the accumulator.
+*/
template <typename... Ts>
auto sample(Ts&&... ts) noexcept {
return sample_type<std::tuple<Ts...>>{std::forward_as_tuple(std::forward<Ts>(ts)...)};
}
-#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
template <class T>
struct weight_type {
T value;
@@ -417,7 +481,6 @@ template <class T>
struct sample_type {
T value;
};
-#endif
} // namespace histogram
} // namespace boost
diff --git a/boost/histogram/indexed.hpp b/boost/histogram/indexed.hpp
index 1c31cafcfe..3b4ec823e4 100644
--- a/boost/histogram/indexed.hpp
+++ b/boost/histogram/indexed.hpp
@@ -7,21 +7,20 @@
#ifndef BOOST_HISTOGRAM_INDEXED_HPP
#define BOOST_HISTOGRAM_INDEXED_HPP
+#include <array>
#include <boost/histogram/axis/traits.hpp>
#include <boost/histogram/detail/attribute.hpp>
#include <boost/histogram/detail/axes.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/iterator_adaptor.hpp>
+#include <boost/histogram/detail/operators.hpp>
#include <boost/histogram/fwd.hpp>
-#include <boost/histogram/unsafe_access.hpp>
-#include <boost/iterator/iterator_adaptor.hpp>
#include <type_traits>
#include <utility>
namespace boost {
namespace histogram {
-/**
- Coverage mode of the indexed range generator.
+/** Coverage mode of the indexed range generator.
Defines options for the iteration strategy.
*/
@@ -30,185 +29,315 @@ enum class coverage {
all, /*!< iterate over all bins, including underflow and overflow */
};
-/// Range over histogram bins with multi-dimensional index.
+/** Input iterator range over histogram bins with multi-dimensional index.
+
+ The iterator returned by begin() can only be incremented. begin() may only be called
+ once, calling it a second time returns the end() iterator. If several copies of the
+ input iterators exist, the other copies become invalid if one of them is incremented.
+*/
template <class Histogram>
-class BOOST_HISTOGRAM_DETAIL_NODISCARD indexed_range {
- using max_dim = mp11::mp_size_t<
- detail::buffer_size<typename detail::remove_cvref_t<Histogram>::axes_type>::value>;
- using value_iterator = decltype(std::declval<Histogram>().begin());
- struct cache_item {
- int idx, begin, end, extent;
- };
+class BOOST_HISTOGRAM_NODISCARD indexed_range {
+private:
+ using histogram_type = Histogram;
+ static constexpr std::size_t buffer_size =
+ detail::buffer_size<typename std::remove_const_t<histogram_type>::axes_type>::value;
public:
- /**
- Pointer-like class to access value and index of current cell.
-
- Its methods allow one to query the current indices and bins. Furthermore, it acts like
- a pointer to the cell value.
+ using value_iterator = decltype(std::declval<histogram_type>().begin());
+ using value_reference = typename value_iterator::reference;
+ using value_type = typename value_iterator::value_type;
+
+ class iterator;
+ using range_iterator = iterator; ///< deprecated
+
+ /** Pointer-like class to access value and index of current cell.
+
+ Its methods provide access to the current indices and bins and it acts like a pointer
+ to the cell value. To interoperate with the algorithms of the standard library, the
+ accessor is implicitly convertible to a cell value. Assignments and comparisons
+ are passed through to the cell. The accessor is coupled to its parent
+ iterator. Moving the parent iterator forward also updates the linked
+ accessor. Accessors are not copyable. They cannot be stored in containers, but
+ range_iterators can be stored.
*/
- class accessor {
+ class accessor : detail::mirrored<accessor, void> {
public:
/// Array-like view into the current multi-dimensional index.
class index_view {
+ using index_pointer = const typename iterator::index_data*;
+
public:
-#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
- class index_iterator
- : public boost::iterator_adaptor<index_iterator, const cache_item*> {
+ using const_reference = const axis::index_type&;
+ using reference = const_reference; ///< deprecated
+
+ /// implementation detail
+ class const_iterator
+ : public detail::iterator_adaptor<const_iterator, index_pointer,
+ const_reference> {
public:
- index_iterator(const cache_item* i) : index_iterator::iterator_adaptor_(i) {}
- decltype(auto) operator*() const noexcept { return index_iterator::base()->idx; }
+ const_reference operator*() const noexcept { return const_iterator::base()->idx; }
+
+ private:
+ explicit const_iterator(index_pointer i) noexcept
+ : const_iterator::iterator_adaptor_(i) {}
+
+ friend class index_view;
};
-#endif
- auto begin() const noexcept { return index_iterator(begin_); }
- auto end() const noexcept { return index_iterator(end_); }
- auto size() const noexcept { return static_cast<std::size_t>(end_ - begin_); }
- int operator[](unsigned d) const noexcept { return begin_[d].idx; }
- int at(unsigned d) const { return begin_[d].idx; }
+ const_iterator begin() const noexcept { return const_iterator{begin_}; }
+ const_iterator end() const noexcept { return const_iterator{end_}; }
+ std::size_t size() const noexcept {
+ return static_cast<std::size_t>(end_ - begin_);
+ }
+ const_reference operator[](unsigned d) const noexcept { return begin_[d].idx; }
+ const_reference at(unsigned d) const { return begin_[d].idx; }
private:
- index_view(const cache_item* b, const cache_item* e) : begin_(b), end_(e) {}
- const cache_item *begin_, *end_;
+ /// implementation detail
+ index_view(index_pointer b, index_pointer e) : begin_(b), end_(e) {}
+
+ index_pointer begin_, end_;
friend class accessor;
};
- /// Returns the cell value.
- decltype(auto) operator*() const noexcept { return *iter_; }
- /// Returns the cell value.
- decltype(auto) get() const noexcept { return *iter_; }
+ // assignment is pass-through
+ accessor& operator=(const accessor& o) {
+ get() = o.get();
+ return *this;
+ }
+
+ // assignment is pass-through
+ template <class T>
+ accessor& operator=(const T& x) {
+ get() = x;
+ return *this;
+ }
+
+ /// Returns the cell reference.
+ value_reference get() const noexcept { return *(iter_.iter_); }
+ /// @copydoc get()
+ value_reference operator*() const noexcept { return get(); }
/// Access fields and methods of the cell object.
- decltype(auto) operator-> () const noexcept { return iter_; }
+ value_iterator operator->() const noexcept { return iter_.iter_; }
/// Access current index.
/// @param d axis dimension.
- int index(unsigned d = 0) const noexcept { return parent_.cache_[d].idx; }
+ axis::index_type index(unsigned d = 0) const noexcept {
+ return iter_.indices_[d].idx;
+ }
/// Access indices as an iterable range.
- auto indices() const noexcept {
- return index_view(parent_.cache_, parent_.cache_ + parent_.hist_.rank());
+ index_view indices() const noexcept {
+ BOOST_ASSERT(iter_.indices_.hist_);
+ return {iter_.indices_.data(),
+ iter_.indices_.data() + iter_.indices_.hist_->rank()};
}
/// Access current bin.
/// @tparam N axis dimension.
template <unsigned N = 0>
decltype(auto) bin(std::integral_constant<unsigned, N> = {}) const {
- return parent_.hist_.axis(std::integral_constant<unsigned, N>()).bin(index(N));
+ BOOST_ASSERT(iter_.indices_.hist_);
+ return iter_.indices_.hist_->axis(std::integral_constant<unsigned, N>())
+ .bin(index(N));
}
/// Access current bin.
/// @param d axis dimension.
- decltype(auto) bin(unsigned d) const { return parent_.hist_.axis(d).bin(index(d)); }
+ decltype(auto) bin(unsigned d) const {
+ BOOST_ASSERT(iter_.indices_.hist_);
+ return iter_.indices_.hist_->axis(d).bin(index(d));
+ }
- /**
- Computes density in current cell.
+ /** Computes density in current cell.
The density is computed as the cell value divided by the product of bin widths. Axes
without bin widths, like axis::category, are treated as having unit bin with.
*/
double density() const {
+ BOOST_ASSERT(iter_.indices_.hist_);
double x = 1;
- auto it = parent_.cache_;
- parent_.hist_.for_each_axis([&](const auto& a) {
- const auto w = axis::traits::width_as<double>(a, it++->idx);
+ unsigned d = 0;
+ iter_.indices_.hist_->for_each_axis([&](const auto& a) {
+ const auto w = axis::traits::width_as<double>(a, this->index(d++));
x *= w ? w : 1;
});
- return *iter_ / x;
+ return get() / x;
}
+ // forward all comparison operators to the value
+ bool operator<(const accessor& o) noexcept { return get() < o.get(); }
+ bool operator>(const accessor& o) noexcept { return get() > o.get(); }
+ bool operator==(const accessor& o) noexcept { return get() == o.get(); }
+ bool operator!=(const accessor& o) noexcept { return get() != o.get(); }
+ bool operator<=(const accessor& o) noexcept { return get() <= o.get(); }
+ bool operator>=(const accessor& o) noexcept { return get() >= o.get(); }
+
+ template <class U>
+ bool operator<(const U& o) const noexcept {
+ return get() < o;
+ }
+
+ template <class U>
+ bool operator>(const U& o) const noexcept {
+ return get() > o;
+ }
+
+ template <class U>
+ bool operator==(const U& o) const noexcept {
+ return get() == o;
+ }
+
+ template <class U>
+ bool operator!=(const U& o) const noexcept {
+ return get() != o;
+ }
+
+ template <class U>
+ bool operator<=(const U& o) const noexcept {
+ return get() <= o;
+ }
+
+ template <class U>
+ bool operator>=(const U& o) const noexcept {
+ return get() >= o;
+ }
+
+ operator value_type() const noexcept { return get(); }
+
private:
- accessor(indexed_range& p, value_iterator i) : parent_(p), iter_(i) {}
- indexed_range& parent_;
- value_iterator iter_;
- friend class indexed_range;
+ accessor(iterator& i) noexcept : iter_(i) {}
+
+ accessor(const accessor&) = default; // only callable by indexed_range::iterator
+
+ iterator& iter_;
+
+ friend class iterator;
};
- class range_iterator
- : public boost::iterator_adaptor<range_iterator, value_iterator, accessor,
- std::forward_iterator_tag, accessor> {
+ /// implementation detail
+ class iterator {
public:
- accessor operator*() const noexcept { return {*parent_, range_iterator::base()}; }
+ using value_type = typename indexed_range::value_type;
+ using reference = accessor;
private:
- range_iterator(indexed_range* p, value_iterator i) noexcept
- : range_iterator::iterator_adaptor_(i), parent_(p) {}
+ struct pointer_proxy {
+ reference* operator->() noexcept { return std::addressof(ref_); }
+ reference ref_;
+ };
+
+ public:
+ using pointer = pointer_proxy;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::forward_iterator_tag;
+
+ reference operator*() noexcept { return *this; }
+ pointer operator->() noexcept { return pointer_proxy{operator*()}; }
- void increment() noexcept {
+ iterator& operator++() {
+ BOOST_ASSERT(indices_.hist_);
std::size_t stride = 1;
- auto c = parent_->cache_;
+ auto c = indices_.begin();
++c->idx;
- ++range_iterator::base_reference();
- while (c->idx == c->end && (c != (parent_->cache_ + parent_->hist_.rank() - 1))) {
+ ++iter_;
+ while (c->idx == c->end && (c != (indices_.end() - 1))) {
c->idx = c->begin;
- range_iterator::base_reference() -= (c->end - c->begin) * stride;
+ iter_ -= (c->end - c->begin) * stride;
stride *= c->extent;
++c;
++c->idx;
- range_iterator::base_reference() += stride;
+ iter_ += stride;
}
+ return *this;
}
- mutable indexed_range* parent_;
+ iterator operator++(int) {
+ auto prev = *this;
+ operator++();
+ return prev;
+ }
+
+ bool operator==(const iterator& x) const noexcept { return iter_ == x.iter_; }
+ bool operator!=(const iterator& x) const noexcept { return !operator==(x); }
+
+ private:
+ iterator(histogram_type* h) : iter_(h->begin()), indices_(h) {}
+
+ value_iterator iter_;
+
+ struct index_data {
+ axis::index_type idx, begin, end, extent;
+ };
+
+ struct indices_t : std::array<index_data, buffer_size> {
+ using base_type = std::array<index_data, buffer_size>;
+
+ indices_t(histogram_type* h) noexcept : hist_{h} {}
+
+ constexpr auto end() noexcept { return base_type::begin() + hist_->rank(); }
+ constexpr auto end() const noexcept { return base_type::begin() + hist_->rank(); }
+ histogram_type* hist_;
+ } indices_;
- friend class boost::iterator_core_access;
friend class indexed_range;
};
- indexed_range(Histogram& h, coverage c)
- : hist_(h), cover_all_(c == coverage::all), begin_(hist_.begin()), end_(begin_) {
- auto ca = cache_;
- const auto clast = ca + hist_.rank() - 1;
+ indexed_range(histogram_type& hist, coverage cov) : begin_(&hist), end_(&hist) {
std::size_t stride = 1;
- h.for_each_axis([&, this](const auto& a) {
- using opt = axis::traits::static_options<decltype(a)>;
- constexpr int under = opt::test(axis::option::underflow);
- constexpr int over = opt::test(axis::option::overflow);
- const auto size = a.size();
-
- ca->extent = size + under + over;
- // -1 if underflow and cover all, else 0
- ca->begin = cover_all_ ? -under : 0;
- // size + 1 if overflow and cover all, else size
- ca->end = cover_all_ ? size + over : size;
- ca->idx = ca->begin;
-
- begin_ += (ca->begin + under) * stride;
- if (ca < clast)
- end_ += (ca->begin + under) * stride;
- else
- end_ += (ca->end + under) * stride;
-
- stride *= ca->extent;
- ++ca;
- });
+ auto ca = begin_.indices_.begin();
+ const auto clast = ca + begin_.indices_.hist_->rank() - 1;
+ begin_.indices_.hist_->for_each_axis(
+ [ca, clast, cov, &stride, this](const auto& a) mutable {
+ using opt = axis::traits::static_options<decltype(a)>;
+ constexpr int under = opt::test(axis::option::underflow);
+ constexpr int over = opt::test(axis::option::overflow);
+ const auto size = a.size();
+
+ ca->extent = size + under + over;
+ // -1 if underflow and cover all, else 0
+ ca->begin = cov == coverage::all ? -under : 0;
+ // size + 1 if overflow and cover all, else size
+ ca->end = cov == coverage::all ? size + over : size;
+ ca->idx = ca->begin;
+
+ begin_.iter_ += (ca->begin + under) * stride;
+ end_.iter_ += ((ca < clast ? ca->begin : ca->end) + under) * stride;
+
+ stride *= ca->extent;
+ ++ca;
+ });
}
- range_iterator begin() noexcept { return {this, begin_}; }
- range_iterator end() noexcept { return {nullptr, end_}; }
+ iterator begin() noexcept { return begin_; }
+ iterator end() noexcept { return end_; }
private:
- Histogram& hist_;
- const bool cover_all_;
- value_iterator begin_, end_;
- mutable cache_item cache_[max_dim::value];
+ iterator begin_, end_;
};
-/**
- Generates a range over the histogram entries.
+/** Generates an indexed range of <a
+ href="https://en.cppreference.com/w/cpp/named_req/ForwardIterator">forward iterators</a>
+ over the histogram cells.
Use this in a range-based for loop:
```
- for (auto x : indexed(hist)) { ... }
+ for (auto&& x : indexed(hist)) { ... }
```
- The iterators dereference to an indexed_range::accessor, which has methods to query the
- current indices and bins, and acts like a pointer to the cell value.
+ This generates an optimized loop which is nearly always faster than a hand-written loop
+ over the histogram cells. The iterators dereference to an indexed_range::accessor, which
+ has methods to query the current indices and bins and acts like a pointer to the cell
+ value. The returned iterators are forward iterators. They can be stored in a container,
+ but may not be used after the life-time of the histogram ends.
+
+ @returns indexed_range
@param hist Reference to the histogram.
@param cov Iterate over all or only inner bins (optional, default: inner).
*/
-template <typename Histogram>
+template <class Histogram>
auto indexed(Histogram&& hist, coverage cov = coverage::inner) {
return indexed_range<std::remove_reference_t<Histogram>>{std::forward<Histogram>(hist),
cov};
diff --git a/boost/histogram/make_histogram.hpp b/boost/histogram/make_histogram.hpp
index a777b223d9..818fc1893f 100644
--- a/boost/histogram/make_histogram.hpp
+++ b/boost/histogram/make_histogram.hpp
@@ -13,7 +13,6 @@
*/
#include <boost/histogram/accumulators/weighted_sum.hpp>
-#include <boost/histogram/detail/meta.hpp>
#include <boost/histogram/histogram.hpp>
#include <boost/histogram/storage_adaptor.hpp>
#include <boost/histogram/unlimited_storage.hpp> // = default_storage
@@ -30,10 +29,12 @@ namespace histogram {
@param axis First axis instance.
@param axes Other axis instances.
*/
-template <class Storage, class Axis, class... Axes, class = detail::requires_axis<Axis>>
+template <class Storage, class Axis, class... Axes,
+ class = detail::requires_storage_or_adaptible<Storage>,
+ class = detail::requires_axis<Axis>>
auto make_histogram_with(Storage&& storage, Axis&& axis, Axes&&... axes) {
auto a = std::make_tuple(std::forward<Axis>(axis), std::forward<Axes>(axes)...);
- using U = detail::remove_cvref_t<Storage>;
+ using U = std::decay_t<Storage>;
using S = mp11::mp_if<detail::is_storage<U>, U, storage_adaptor<U>>;
return histogram<decltype(a), S>(std::move(a), S(std::forward<Storage>(storage)));
}
@@ -66,11 +67,12 @@ auto make_weighted_histogram(Axis&& axis, Axes&&... axes) {
@param iterable Iterable range of axis objects.
*/
template <class Storage, class Iterable,
+ class = detail::requires_storage_or_adaptible<Storage>,
class = detail::requires_sequence_of_any_axis<Iterable>>
auto make_histogram_with(Storage&& storage, Iterable&& iterable) {
- using U = detail::remove_cvref_t<Storage>;
+ using U = std::decay_t<Storage>;
using S = mp11::mp_if<detail::is_storage<U>, U, storage_adaptor<U>>;
- using It = detail::remove_cvref_t<Iterable>;
+ using It = std::decay_t<Iterable>;
using A = mp11::mp_if<detail::is_indexable_container<It>, It,
std::vector<mp11::mp_first<It>>>;
return histogram<A, S>(std::forward<Iterable>(iterable),
@@ -101,9 +103,11 @@ auto make_weighted_histogram(Iterable&& iterable) {
@param begin Iterator to range of axis objects.
@param end Iterator to range of axis objects.
*/
-template <class Storage, class Iterator, class = detail::requires_iterator<Iterator>>
+template <class Storage, class Iterator,
+ class = detail::requires_storage_or_adaptible<Storage>,
+ class = detail::requires_iterator<Iterator>>
auto make_histogram_with(Storage&& storage, Iterator begin, Iterator end) {
- using T = detail::remove_cvref_t<decltype(*begin)>;
+ using T = std::decay_t<decltype(*begin)>;
return make_histogram_with(std::forward<Storage>(storage), std::vector<T>(begin, end));
}
diff --git a/boost/histogram/ostream.hpp b/boost/histogram/ostream.hpp
index bef4a78e30..e38a0600cd 100644
--- a/boost/histogram/ostream.hpp
+++ b/boost/histogram/ostream.hpp
@@ -12,6 +12,17 @@
#include <boost/histogram/fwd.hpp>
#include <iosfwd>
+/**
+ \file boost/histogram/ostream.hpp
+
+ A simple streaming operator for the histogram type. The text representation is
+ rudimentary and not guaranteed to be stable between versions of Boost.Histogram. This
+ header is not included by any other header and must be explicitly included to use the
+ streaming operator.
+
+ To you use your own, simply include your own implementation instead of this header.
+ */
+
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
namespace boost {
diff --git a/boost/histogram/serialization.hpp b/boost/histogram/serialization.hpp
index 832c3cc6be..0f4c93acd6 100644
--- a/boost/histogram/serialization.hpp
+++ b/boost/histogram/serialization.hpp
@@ -7,6 +7,7 @@
#ifndef BOOST_HISTOGRAM_SERIALIZATION_HPP
#define BOOST_HISTOGRAM_SERIALIZATION_HPP
+#include <boost/archive/archive_exception.hpp>
#include <boost/assert.hpp>
#include <boost/histogram/accumulators/mean.hpp>
#include <boost/histogram/accumulators/sum.hpp>
@@ -21,12 +22,15 @@
#include <boost/histogram/storage_adaptor.hpp>
#include <boost/histogram/unlimited_storage.hpp>
#include <boost/histogram/unsafe_access.hpp>
+#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/tuple.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/serialization.hpp>
+#include <boost/serialization/split_member.hpp>
#include <boost/serialization/string.hpp>
-#include <boost/serialization/variant.hpp>
+#include <boost/serialization/throw_exception.hpp>
#include <boost/serialization/vector.hpp>
#include <tuple>
#include <type_traits>
@@ -83,6 +87,13 @@ void weighted_mean<RealType>::serialize(Archive& ar, unsigned /* version */) {
ar& serialization::make_nvp("sum_of_weighted_deltas_squared",
sum_of_weighted_deltas_squared_);
}
+
+template <class Archive, class T>
+void serialize(Archive& ar, thread_safe<T>& t, unsigned /* version */) {
+ T value = t;
+ ar& serialization::make_nvp("value", value);
+ t = value;
+}
} // namespace accumulators
namespace axis {
@@ -138,10 +149,51 @@ void category<T, M, O, A>::serialize(Archive& ar, unsigned /* version */) {
ar& serialization::make_nvp("meta", vec_meta_.second());
}
-template <class... Ts>
-template <class Archive>
-void variant<Ts...>::serialize(Archive& ar, unsigned /* version */) {
- ar& serialization::make_nvp("variant", impl);
+// variant_proxy is a workaround to remain backward compatible in the serialization
+// format. It uses only the public interface of axis::variant for serialization and
+// therefore works independently of the underlying variant implementation.
+template <class Variant>
+struct variant_proxy {
+ Variant& v;
+
+ BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+ template <class Archive>
+ void save(Archive& ar, unsigned /* version */) const {
+ visit(
+ [&ar](auto& value) {
+ using T = std::decay_t<decltype(value)>;
+ int which = static_cast<int>(mp11::mp_find<Variant, T>::value);
+ ar << serialization::make_nvp("which", which);
+ ar << serialization::make_nvp("value", value);
+ },
+ v);
+ }
+
+ template <class Archive>
+ void load(Archive& ar, unsigned /* version */) {
+ int which = 0;
+ ar >> serialization::make_nvp("which", which);
+ constexpr unsigned N = mp11::mp_size<Variant>::value;
+ if (which < 0 || static_cast<unsigned>(which) >= N)
+ // throw on invalid which, which >= N can happen if type was removed from variant
+ serialization::throw_exception(
+ archive::archive_exception(archive::archive_exception::unsupported_version));
+ mp11::mp_with_index<N>(static_cast<unsigned>(which), [&ar, this](auto i) {
+ using T = mp11::mp_at_c<Variant, i>;
+ T value;
+ ar >> serialization::make_nvp("value", value);
+ v = std::move(value);
+ T* new_address = get_if<T>(&v);
+ ar.reset_object_address(new_address, &value);
+ });
+ }
+};
+
+template <class Archive, class... Ts>
+void serialize(Archive& ar, variant<Ts...>& v, unsigned /* version */) {
+ variant_proxy<variant<Ts...>> p{v};
+ ar& serialization::make_nvp("variant", p);
}
} // namespace axis
@@ -165,35 +217,37 @@ void serialize(Archive& ar, map_impl<T>& impl, unsigned /* version */) {
}
template <class Archive, class Allocator>
-void serialize(Archive& ar, mp_int<Allocator>& x, unsigned /* version */) {
+void serialize(Archive& ar, large_int<Allocator>& x, unsigned /* version */) {
ar& serialization::make_nvp("data", x.data);
}
} // namespace detail
template <class Archive, class T>
-void serialize(Archive& ar, storage_adaptor<T>& s, unsigned /* version */) {
- ar& serialization::make_nvp("impl", static_cast<detail::storage_adaptor_impl<T>&>(s));
+void serialize(Archive& ar, storage_adaptor<T>& x, unsigned /* version */) {
+ auto& impl = unsafe_access::storage_adaptor_impl(x);
+ ar& serialization::make_nvp("impl", impl);
}
-template <class A>
-template <class Archive>
-void unlimited_storage<A>::serialize(Archive& ar, unsigned /* version */) {
+template <class Allocator, class Archive>
+void serialize(Archive& ar, unlimited_storage<Allocator>& s, unsigned /* version */) {
+ auto& buffer = unsafe_access::unlimited_storage_buffer(s);
+ using buffer_t = std::remove_reference_t<decltype(buffer)>;
if (Archive::is_loading::value) {
- buffer_type dummy(buffer.alloc);
+ buffer_t helper(buffer.alloc);
std::size_t size;
- ar& serialization::make_nvp("type", dummy.type);
+ ar& serialization::make_nvp("type", helper.type);
ar& serialization::make_nvp("size", size);
- dummy.apply([this, size](auto* tp) {
+ helper.visit([&buffer, size](auto* tp) {
BOOST_ASSERT(tp == nullptr);
- using T = detail::remove_cvref_t<decltype(*tp)>;
+ using T = std::decay_t<decltype(*tp)>;
buffer.template make<T>(size);
});
} else {
ar& serialization::make_nvp("type", buffer.type);
ar& serialization::make_nvp("size", buffer.size);
}
- buffer.apply([this, &ar](auto* tp) {
- using T = detail::remove_cvref_t<decltype(*tp)>;
+ buffer.visit([&buffer, &ar](auto* tp) {
+ using T = std::decay_t<decltype(*tp)>;
ar& serialization::make_nvp(
"buffer",
serialization::make_array(reinterpret_cast<T*>(buffer.ptr), buffer.size));
diff --git a/boost/histogram/storage_adaptor.hpp b/boost/histogram/storage_adaptor.hpp
index 15e8cc4162..4e278a690b 100644
--- a/boost/histogram/storage_adaptor.hpp
+++ b/boost/histogram/storage_adaptor.hpp
@@ -1,4 +1,4 @@
-// Copyright 2018 Hans Dembinski
+// Copyright 2018-2019 Hans Dembinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
@@ -8,13 +8,14 @@
#define BOOST_HISTOGRAM_STORAGE_ADAPTOR_HPP
#include <algorithm>
-#include <boost/assert.hpp>
#include <boost/histogram/detail/cat.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/histogram/detail/detect.hpp>
+#include <boost/histogram/detail/iterator_adaptor.hpp>
+#include <boost/histogram/detail/safe_comparison.hpp>
#include <boost/histogram/fwd.hpp>
-#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/mp11/utility.hpp>
#include <boost/throw_exception.hpp>
+#include <iosfwd>
#include <stdexcept>
#include <type_traits>
@@ -24,16 +25,23 @@ namespace detail {
template <class T>
struct vector_impl : T {
- vector_impl() = default;
+ using allocator_type = typename T::allocator_type;
+ static constexpr bool has_threading_support =
+ accumulators::is_thread_safe<typename T::value_type>::value;
+
+ vector_impl(const allocator_type& a = {}) : T(a) {}
+ vector_impl(const vector_impl&) = default;
+ vector_impl& operator=(const vector_impl&) = default;
+ vector_impl(vector_impl&&) = default;
+ vector_impl& operator=(vector_impl&&) = default;
+
+ explicit vector_impl(T&& t) : T(std::move(t)) {}
explicit vector_impl(const T& t) : T(t) {}
- explicit vector_impl(typename T::allocator_type a) : T(a) {}
template <class U, class = requires_iterable<U>>
- explicit vector_impl(const U& u) {
- T::reserve(u.size());
- for (auto&& x : u) T::emplace_back(x);
- }
+ explicit vector_impl(const U& u, const allocator_type& a = {})
+ : T(std::begin(u), std::end(u), a) {}
template <class U, class = requires_iterable<U>>
vector_impl& operator=(const U& u) {
@@ -49,17 +57,29 @@ struct vector_impl : T {
T::resize(n, value_type());
std::fill_n(T::begin(), std::min(n, old_size), value_type());
}
-};
+}; // namespace detail
template <class T>
struct array_impl : T {
+ static constexpr bool has_threading_support =
+ accumulators::is_thread_safe<typename T::value_type>::value;
+
array_impl() = default;
+ array_impl(const array_impl& t) : T(t), size_(t.size_) {}
+ array_impl& operator=(const array_impl& t) {
+ T::operator=(t);
+ size_ = t.size_;
+ return *this;
+ }
+ explicit array_impl(T&& t) : T(std::move(t)) {}
explicit array_impl(const T& t) : T(t) {}
+
template <class U, class = requires_iterable<U>>
explicit array_impl(const U& u) : size_(u.size()) {
- std::size_t i = 0;
- for (auto&& x : u) T::operator[](i++) = x;
+ using std::begin;
+ using std::end;
+ std::copy(begin(u), end(u), this->begin());
}
template <class U, class = requires_iterable<U>>
@@ -98,10 +118,18 @@ struct map_impl : T {
using value_type = typename T::mapped_type;
using const_reference = const value_type&;
+ static constexpr bool has_threading_support = false;
+ static_assert(
+ !accumulators::is_thread_safe<value_type>::value,
+ "std::map and std::unordered_map do not support thread-safe element access. "
+ "If you have a map with thread-safe element access, please file an issue and"
+ "support will be added.");
+
struct reference {
reference(map_impl* m, std::size_t i) noexcept : map(m), idx(i) {}
+
reference(const reference&) noexcept = default;
- reference operator=(reference o) {
+ reference& operator=(const reference& o) {
if (this != &o) operator=(static_cast<const_reference>(o));
return *this;
}
@@ -110,15 +138,14 @@ struct map_impl : T {
return static_cast<const map_impl*>(map)->operator[](idx);
}
- template <class U, class = requires_convertible<U, value_type>>
- reference& operator=(const U& u) {
+ reference& operator=(const_reference u) {
auto it = map->find(idx);
- if (u == value_type()) {
- if (it != static_cast<T*>(map)->end()) map->erase(it);
+ if (u == value_type{}) {
+ if (it != static_cast<T*>(map)->end()) { map->erase(it); }
} else {
- if (it != static_cast<T*>(map)->end())
+ if (it != static_cast<T*>(map)->end()) {
it->second = u;
- else {
+ } else {
map->emplace(idx, u);
}
}
@@ -127,29 +154,31 @@ struct map_impl : T {
template <class U, class V = value_type,
class = std::enable_if_t<has_operator_radd<V, U>::value>>
- reference operator+=(const U& u) {
+ reference& operator+=(const U& u) {
auto it = map->find(idx);
- if (it != static_cast<T*>(map)->end())
+ if (it != static_cast<T*>(map)->end()) {
it->second += u;
- else
+ } else {
map->emplace(idx, u);
+ }
return *this;
}
template <class U, class V = value_type,
class = std::enable_if_t<has_operator_rsub<V, U>::value>>
- reference operator-=(const U& u) {
+ reference& operator-=(const U& u) {
auto it = map->find(idx);
- if (it != static_cast<T*>(map)->end())
+ if (it != static_cast<T*>(map)->end()) {
it->second -= u;
- else
+ } else {
map->emplace(idx, -u);
+ }
return *this;
}
template <class U, class V = value_type,
class = std::enable_if_t<has_operator_rmul<V, U>::value>>
- reference operator*=(const U& u) {
+ reference& operator*=(const U& u) {
auto it = map->find(idx);
if (it != static_cast<T*>(map)->end()) it->second *= u;
return *this;
@@ -157,12 +186,13 @@ struct map_impl : T {
template <class U, class V = value_type,
class = std::enable_if_t<has_operator_rdiv<V, U>::value>>
- reference operator/=(const U& u) {
+ reference& operator/=(const U& u) {
auto it = map->find(idx);
- if (it != static_cast<T*>(map)->end())
+ if (it != static_cast<T*>(map)->end()) {
it->second /= u;
- else if (!(value_type{} / u == value_type{}))
+ } else if (!(value_type{} / u == value_type{})) {
map->emplace(idx, value_type{} / u);
+ }
return *this;
}
@@ -170,21 +200,41 @@ struct map_impl : T {
class = std::enable_if_t<has_operator_preincrement<V>::value>>
reference operator++() {
auto it = map->find(idx);
- if (it != static_cast<T*>(map)->end())
+ if (it != static_cast<T*>(map)->end()) {
++it->second;
- else
- map->emplace(idx, 1);
+ } else {
+ value_type tmp{};
+ ++tmp;
+ map->emplace(idx, tmp);
+ }
return *this;
}
template <class V = value_type,
class = std::enable_if_t<has_operator_preincrement<V>::value>>
value_type operator++(int) {
- const value_type tmp = operator const_reference();
+ const value_type tmp = *this;
operator++();
return tmp;
}
+ template <class U, class = std::enable_if_t<has_operator_equal<value_type, U>::value>>
+ bool operator==(const U& rhs) const {
+ return operator const_reference() == rhs;
+ }
+
+ template <class U, class = std::enable_if_t<has_operator_equal<value_type, U>::value>>
+ bool operator!=(const U& rhs) const {
+ return !operator==(rhs);
+ }
+
+ template <typename CharT, typename Traits>
+ friend std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os, reference x) {
+ os << static_cast<const_reference>(x);
+ return os;
+ }
+
template <class... Ts>
decltype(auto) operator()(Ts&&... args) {
return map->operator[](idx)(std::forward<Ts>(args)...);
@@ -196,9 +246,7 @@ struct map_impl : T {
template <class Value, class Reference, class MapPtr>
struct iterator_t
- : boost::iterator_adaptor<iterator_t<Value, Reference, MapPtr>, std::size_t, Value,
- std::random_access_iterator_tag, Reference,
- std::ptrdiff_t> {
+ : iterator_adaptor<iterator_t<Value, Reference, MapPtr>, std::size_t, Reference> {
iterator_t() = default;
template <class V, class R, class M, class = requires_convertible<M, MapPtr>>
iterator_t(const iterator_t<V, R, M>& it) noexcept : iterator_t(it.map_, it.base()) {}
@@ -208,20 +256,27 @@ struct map_impl : T {
bool equal(const iterator_t<V, R, M>& rhs) const noexcept {
return map_ == rhs.map_ && iterator_t::base() == rhs.base();
}
- decltype(auto) dereference() const { return (*map_)[iterator_t::base()]; }
+ Reference operator*() const { return (*map_)[iterator_t::base()]; }
MapPtr map_ = nullptr;
};
using iterator = iterator_t<value_type, reference, map_impl*>;
using const_iterator = iterator_t<const value_type, const_reference, const map_impl*>;
- map_impl() = default;
+ using allocator_type = typename T::allocator_type;
+
+ map_impl(const allocator_type& a = {}) : T(a) {}
- explicit map_impl(const T& t) : T(t) {}
- explicit map_impl(typename T::allocator_type a) : T(a) {}
+ map_impl(const map_impl&) = default;
+ map_impl& operator=(const map_impl&) = default;
+ map_impl(map_impl&&) = default;
+ map_impl& operator=(map_impl&&) = default;
+
+ map_impl(const T& t) : T(t), size_(t.size()) {}
+ map_impl(T&& t) : T(std::move(t)), size_(t.size()) {}
template <class U, class = requires_iterable<U>>
- explicit map_impl(const U& u) : size_(u.size()) {
+ explicit map_impl(const U& u, const allocator_type& a = {}) : T(a), size_(u.size()) {
using std::begin;
using std::end;
std::copy(begin(u), end(u), this->begin());
@@ -263,33 +318,53 @@ struct map_impl : T {
std::size_t size_ = 0;
};
-template <typename T>
+template <class T>
struct ERROR_type_passed_to_storage_adaptor_not_recognized;
-template <typename T>
-using storage_adaptor_impl = mp11::mp_if<
+// clang-format off
+template <class T>
+using storage_adaptor_impl =
+ mp11::mp_cond<
is_vector_like<T>, vector_impl<T>,
- mp11::mp_if<is_array_like<T>, array_impl<T>,
- mp11::mp_if<is_map_like<T>, map_impl<T>,
- ERROR_type_passed_to_storage_adaptor_not_recognized<T>>>>;
-
+ is_array_like<T>, array_impl<T>,
+ is_map_like<T>, map_impl<T>,
+ std::true_type, ERROR_type_passed_to_storage_adaptor_not_recognized<T>
+ >;
+// clang-format on
} // namespace detail
-/// Turns any vector-like array-like, and map-like container into a storage type.
-template <typename T>
+/// Turns any vector-like, array-like, and map-like container into a storage type.
+template <class T>
class storage_adaptor : public detail::storage_adaptor_impl<T> {
- using base_type = detail::storage_adaptor_impl<T>;
+ using impl_type = detail::storage_adaptor_impl<T>;
public:
- using base_type::base_type;
- using base_type::operator=;
+ // standard copy, move, assign
+ storage_adaptor(storage_adaptor&&) = default;
+ storage_adaptor(const storage_adaptor&) = default;
+ storage_adaptor& operator=(storage_adaptor&&) = default;
+ storage_adaptor& operator=(const storage_adaptor&) = default;
+
+ // forwarding constructor
+ template <class... Ts>
+ storage_adaptor(Ts&&... ts) : impl_type(std::forward<Ts>(ts)...) {}
+
+ // forwarding assign
+ template <class U>
+ storage_adaptor& operator=(U&& u) {
+ impl_type::operator=(std::forward<U>(u));
+ return *this;
+ }
template <class U, class = detail::requires_iterable<U>>
bool operator==(const U& u) const {
using std::begin;
using std::end;
- return std::equal(this->begin(), this->end(), begin(u), end(u));
+ return std::equal(this->begin(), this->end(), begin(u), end(u), detail::safe_equal{});
}
+
+private:
+ friend struct unsafe_access;
};
} // namespace histogram
diff --git a/boost/histogram/unlimited_storage.hpp b/boost/histogram/unlimited_storage.hpp
index 10f3a8b621..bce10986eb 100644
--- a/boost/histogram/unlimited_storage.hpp
+++ b/boost/histogram/unlimited_storage.hpp
@@ -1,4 +1,5 @@
-// Copyright 2015-2017 Hans Dembinski
+// Copyright 2015-2019 Hans Dembinski
+// Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
@@ -9,392 +10,103 @@
#include <algorithm>
#include <boost/assert.hpp>
-#include <boost/config/workaround.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/histogram/detail/meta.hpp>
+#include <boost/core/alloc_construct.hpp>
+#include <boost/core/exchange.hpp>
+#include <boost/histogram/detail/iterator_adaptor.hpp>
+#include <boost/histogram/detail/large_int.hpp>
+#include <boost/histogram/detail/operators.hpp>
+#include <boost/histogram/detail/safe_comparison.hpp>
+#include <boost/histogram/detail/static_if.hpp>
#include <boost/histogram/fwd.hpp>
-#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
#include <cmath>
+#include <cstdint>
#include <functional>
-#include <limits>
+#include <iterator>
#include <memory>
#include <type_traits>
namespace boost {
namespace histogram {
-
namespace detail {
-// version of std::equal_to<> which handles comparison of signed and unsigned
-struct equal {
- template <class T, class U>
- bool operator()(const T& t, const U& u) const noexcept {
- return impl(std::is_signed<T>{}, std::is_signed<U>{}, t, u);
- }
-
- template <class T, class U>
- bool impl(std::false_type, std::false_type, const T& t, const U& u) const noexcept {
- return t == u;
- }
-
- template <class T, class U>
- bool impl(std::false_type, std::true_type, const T& t, const U& u) const noexcept {
- return u >= 0 && t == make_unsigned(u);
- }
-
- template <class T, class U>
- bool impl(std::true_type, std::false_type, const T& t, const U& u) const noexcept {
- return t >= 0 && make_unsigned(t) == u;
- }
-
- template <class T, class U>
- bool impl(std::true_type, std::true_type, const T& t, const U& u) const noexcept {
- return t == u;
- }
-};
-
-// version of std::less<> which handles comparison of signed and unsigned
-struct less {
- template <class T, class U>
- bool operator()(const T& t, const U& u) const noexcept {
- return impl(std::is_signed<T>{}, std::is_signed<U>{}, t, u);
- }
-
- template <class T, class U>
- bool impl(std::false_type, std::false_type, const T& t, const U& u) const noexcept {
- return t < u;
- }
-
- template <class T, class U>
- bool impl(std::false_type, std::true_type, const T& t, const U& u) const noexcept {
- return u >= 0 && t < make_unsigned(u);
- }
-
- template <class T, class U>
- bool impl(std::true_type, std::false_type, const T& t, const U& u) const noexcept {
- return t < 0 || make_unsigned(t) < u;
- }
-
- template <class T, class U>
- bool impl(std::true_type, std::true_type, const T& t, const U& u) const noexcept {
- return t < u;
- }
-};
-
-// version of std::greater<> which handles comparison of signed and unsigned
-struct greater {
- template <class T, class U>
- bool operator()(const T& t, const U& u) const noexcept {
- return impl(std::is_signed<T>{}, std::is_signed<U>{}, t, u);
- }
-
- template <class T, class U>
- bool impl(std::false_type, std::false_type, const T& t, const U& u) const noexcept {
- return t > u;
- }
-
- template <class T, class U>
- bool impl(std::false_type, std::true_type, const T& t, const U& u) const noexcept {
- return u < 0 || t > make_unsigned(u);
- }
-
- template <class T, class U>
- bool impl(std::true_type, std::false_type, const T& t, const U& u) const noexcept {
- return t >= 0 && make_unsigned(t) > u;
- }
-
- template <class T, class U>
- bool impl(std::true_type, std::true_type, const T& t, const U& u) const noexcept {
- return t > u;
- }
-};
-
-template <class Allocator>
-struct mp_int;
-
template <class T>
-struct is_unsigned_integral : mp11::mp_and<std::is_integral<T>, std::is_unsigned<T>> {};
+struct is_large_int : std::false_type {};
-template <class T>
-bool safe_increment(T& t) {
- if (t < std::numeric_limits<T>::max()) {
- ++t;
- return true;
- }
- return false;
-}
+template <class A>
+struct is_large_int<large_int<A>> : std::true_type {};
-template <class T, class U>
-bool safe_radd(T& t, const U& u) {
- static_assert(is_unsigned_integral<T>::value, "T must be unsigned integral type");
- static_assert(is_unsigned_integral<U>::value, "T must be unsigned integral type");
- if (static_cast<T>(std::numeric_limits<T>::max() - t) >= u) {
- t += static_cast<T>(u); // static_cast to suppress conversion warning
- return true;
- }
- return false;
-}
+template <class T, class ReturnType>
+using if_arithmetic_or_large_int =
+ std::enable_if_t<(std::is_arithmetic<T>::value || is_large_int<T>::value),
+ ReturnType>;
-// use boost.multiprecision.cpp_int in your own code, it is much more sophisticated
-// than this implementation; we use it here to reduce coupling between boost libs
-template <class Allocator>
-struct mp_int {
- explicit mp_int(Allocator a = {}) : data(1, 0, std::move(a)) {}
- explicit mp_int(uint64_t v, Allocator a = {}) : data(1, v, std::move(a)) {}
- mp_int(const mp_int&) = default;
- mp_int& operator=(const mp_int&) = default;
- mp_int(mp_int&&) = default;
- mp_int& operator=(mp_int&&) = default;
-
- mp_int& operator=(uint64_t o) {
- data = decltype(data)(1, o);
- return *this;
- }
+template <class L, class T>
+using next_type = mp11::mp_at_c<L, (mp11::mp_find<L, T>::value + 1)>;
- mp_int& operator++() {
- BOOST_ASSERT(data.size() > 0u);
- std::size_t i = 0;
- while (!safe_increment(data[i])) {
- data[i] = 0;
- ++i;
- if (i == data.size()) {
- data.push_back(1);
- break;
- }
- }
- return *this;
- }
-
- mp_int& operator+=(const mp_int& o) {
- if (this == &o) {
- auto tmp{o};
- return operator+=(tmp);
- }
- bool carry = false;
- std::size_t i = 0;
- for (uint64_t oi : o.data) {
- auto& di = maybe_extend(i);
- if (carry) {
- if (safe_increment(oi))
- carry = false;
- else {
- ++i;
- continue;
- }
- }
- if (!safe_radd(di, oi)) {
- add_remainder(di, oi);
- carry = true;
- }
- ++i;
- }
- while (carry) {
- auto& di = maybe_extend(i);
- if (safe_increment(di)) break;
- di = 0;
- ++i;
- }
- return *this;
- }
-
- mp_int& operator+=(uint64_t o) {
- BOOST_ASSERT(data.size() > 0u);
- if (safe_radd(data[0], o)) return *this;
- add_remainder(data[0], o);
- // carry the one, data may grow several times
- std::size_t i = 1;
- while (true) {
- auto& di = maybe_extend(i);
- if (safe_increment(di)) break;
- di = 0;
- ++i;
- }
- return *this;
- }
-
- operator double() const noexcept {
- BOOST_ASSERT(data.size() > 0u);
- double result = static_cast<double>(data[0]);
- std::size_t i = 0;
- while (++i < data.size())
- result += static_cast<double>(data[i]) * std::pow(2.0, i * 64);
- return result;
- }
-
- // total ordering for mp_int, mp_int
- bool operator<(const mp_int& o) const noexcept {
- BOOST_ASSERT(data.size() > 0u);
- BOOST_ASSERT(o.data.size() > 0u);
- // no leading zeros allowed
- BOOST_ASSERT(data.size() == 1 || data.back() > 0u);
- BOOST_ASSERT(o.data.size() == 1 || o.data.back() > 0u);
- if (data.size() < o.data.size()) return true;
- if (data.size() > o.data.size()) return false;
- auto s = data.size();
- while (s > 0u) {
- --s;
- if (data[s] < o.data[s]) return true;
- if (data[s] > o.data[s]) return false;
- }
- return false; // args are equal
- }
-
- bool operator==(const mp_int& o) const noexcept {
- BOOST_ASSERT(data.size() > 0u);
- BOOST_ASSERT(o.data.size() > 0u);
- // no leading zeros allowed
- BOOST_ASSERT(data.size() == 1 || data.back() > 0u);
- BOOST_ASSERT(o.data.size() == 1 || o.data.back() > 0u);
- if (data.size() != o.data.size()) return false;
- return std::equal(data.begin(), data.end(), o.data.begin());
- }
-
- // copied from boost/operators.hpp
- friend bool operator>(const mp_int& x, const mp_int& y) { return y < x; }
- friend bool operator<=(const mp_int& x, const mp_int& y) { return !(y < x); }
- friend bool operator>=(const mp_int& x, const mp_int& y) { return !(x < y); }
- friend bool operator!=(const mp_int& x, const mp_int& y) { return !(x == y); }
-
- // total ordering for mp_int, uint64; partial ordering for mp_int, double
- template <class U>
- bool operator<(const U& o) const noexcept {
- BOOST_ASSERT(data.size() > 0u);
- return static_if<is_unsigned_integral<U>>(
- [this](uint64_t o) { return data.size() == 1 && data[0] < o; },
- [this](double o) { return operator double() < o; }, o);
- }
-
- template <class U>
- bool operator>(const U& o) const noexcept {
- BOOST_ASSERT(data.size() > 0u);
- BOOST_ASSERT(data.back() > 0u); // no leading zeros allowed
- return static_if<is_unsigned_integral<U>>(
- [this](uint64_t o) { return data.size() > 1 || data[0] > o; },
- [this](double o) { return operator double() > o; }, o);
- }
+template <class Allocator>
+class construct_guard {
+public:
+ using pointer = typename std::allocator_traits<Allocator>::pointer;
- template <class U>
- bool operator==(const U& o) const noexcept {
- BOOST_ASSERT(data.size() > 0u);
- return static_if<is_unsigned_integral<U>>(
- [this](uint64_t o) { return data.size() == 1 && data[0] == o; },
- [this](double o) { return operator double() == o; }, o);
- }
+ construct_guard(Allocator& a, pointer p, std::size_t n) noexcept
+ : a_(a), p_(p), n_(n) {}
- // adapted copy from boost/operators.hpp
- template <class U>
- friend bool operator<=(const mp_int& x, const U& y) {
- if (is_unsigned_integral<U>::value) return !(x > y);
- return (x < y) || (x == y);
- }
- template <class U>
- friend bool operator>=(const mp_int& x, const U& y) {
- if (is_unsigned_integral<U>::value) return !(x < y);
- return (x > y) || (x == y);
- }
- template <class U>
- friend bool operator>(const U& x, const mp_int& y) {
- if (is_unsigned_integral<U>::value) return y < x;
- return y < x;
- }
- template <class U>
- friend bool operator<(const U& x, const mp_int& y) {
- if (is_unsigned_integral<U>::value) return y > x;
- return y > x;
- }
- template <class U>
- friend bool operator<=(const U& x, const mp_int& y) {
- if (is_unsigned_integral<U>::value) return !(y < x);
- return (y > x) || (y == x);
- }
- template <class U>
- friend bool operator>=(const U& x, const mp_int& y) {
- if (is_unsigned_integral<U>::value) return !(y > x);
- return (y < x) || (y == x);
- }
- template <class U>
- friend bool operator==(const U& y, const mp_int& x) {
- return x == y;
- }
- template <class U>
- friend bool operator!=(const U& y, const mp_int& x) {
- return !(x == y);
- }
- template <class U>
- friend bool operator!=(const mp_int& y, const U& x) {
- return !(y == x);
+ ~construct_guard() {
+ if (p_) { a_.deallocate(p_, n_); }
}
- uint64_t& maybe_extend(std::size_t i) {
- while (i >= data.size()) data.push_back(0);
- return data[i];
- }
+ void release() { p_ = pointer(); }
- static void add_remainder(uint64_t& d, const uint64_t o) noexcept {
- BOOST_ASSERT(d > 0u);
- // in decimal system it would look like this:
- // 8 + 8 = 6 = 8 - (9 - 8) - 1
- // 9 + 1 = 0 = 9 - (9 - 1) - 1
- auto tmp = std::numeric_limits<uint64_t>::max();
- tmp -= o;
- --d -= tmp;
- }
+ construct_guard(const construct_guard&) = delete;
+ construct_guard& operator=(const construct_guard&) = delete;
- std::vector<uint64_t, Allocator> data;
+private:
+ Allocator& a_;
+ pointer p_;
+ std::size_t n_;
};
template <class Allocator>
-auto create_buffer(Allocator& a, std::size_t n) {
- using AT = std::allocator_traits<Allocator>;
- auto ptr = AT::allocate(a, n); // may throw
+void* buffer_create(Allocator& a, std::size_t n) {
+ auto ptr = a.allocate(n); // may throw
static_assert(std::is_trivially_copyable<decltype(ptr)>::value,
"ptr must be trivially copyable");
- auto it = ptr;
- const auto end = ptr + n;
- try {
- // this loop may throw
- while (it != end) AT::construct(a, it++, typename AT::value_type{});
- } catch (...) {
- // release resources that were already acquired before rethrowing
- while (it != ptr) AT::destroy(a, --it);
- AT::deallocate(a, ptr, n);
- throw;
- }
- return ptr;
+ construct_guard<Allocator> guard(a, ptr, n);
+ boost::alloc_construct_n(a, ptr, n);
+ guard.release();
+ return static_cast<void*>(ptr);
}
template <class Allocator, class Iterator>
-auto create_buffer(Allocator& a, std::size_t n, Iterator iter) {
+auto buffer_create(Allocator& a, std::size_t n, Iterator iter) {
BOOST_ASSERT(n > 0u);
- using AT = std::allocator_traits<Allocator>;
- auto ptr = AT::allocate(a, n); // may throw
+ auto ptr = a.allocate(n); // may throw
static_assert(std::is_trivially_copyable<decltype(ptr)>::value,
"ptr must be trivially copyable");
- auto it = ptr;
- const auto end = ptr + n;
- try {
- // this loop may throw
- while (it != end) AT::construct(a, it++, *iter++);
- } catch (...) {
- // release resources that were already acquired before rethrowing
- while (it != ptr) AT::destroy(a, --it);
- AT::deallocate(a, ptr, n);
- throw;
- }
+ construct_guard<Allocator> guard(a, ptr, n);
+ using T = typename std::allocator_traits<Allocator>::value_type;
+ struct casting_iterator {
+ void operator++() noexcept { ++iter_; }
+ T operator*() noexcept {
+ return static_cast<T>(*iter_);
+ } // silence conversion warnings
+ Iterator iter_;
+ };
+ boost::alloc_construct_n(a, ptr, n, casting_iterator{iter});
+ guard.release();
return ptr;
}
template <class Allocator>
-void destroy_buffer(Allocator& a, typename std::allocator_traits<Allocator>::pointer p,
+void buffer_destroy(Allocator& a, typename std::allocator_traits<Allocator>::pointer p,
std::size_t n) {
BOOST_ASSERT(p);
BOOST_ASSERT(n > 0u);
- using AT = std::allocator_traits<Allocator>;
- auto it = p + n;
- while (it != p) AT::destroy(a, --it);
- AT::deallocate(a, p, n);
+ boost::alloc_destroy_n(a, p, n);
+ a.deallocate(p, n);
}
} // namespace detail
@@ -402,16 +114,16 @@ void destroy_buffer(Allocator& a, typename std::allocator_traits<Allocator>::poi
/**
Memory-efficient storage for integral counters which cannot overflow.
- This storage provides a no-overflow-guarantee if it is filled with integral weights
- only. This storage implementation keeps a contiguous array of elemental counters, one
- for each cell. If an operation is requested, which would overflow a counter, the whole
- array is replaced with another of a wider integral type, then the operation is executed.
- The storage uses integers of 8, 16, 32, 64 bits, and then switches to a multiprecision
+ This storage provides a no-overflow-guarantee if the counters are incremented with
+ integer weights. It maintains a contiguous array of elemental counters, one for each
+ cell. If an operation is requested which would overflow a counter, the array is
+ replaced with another of a wider integral type, then the operation is executed. The
+ storage uses integers of 8, 16, 32, 64 bits, and then switches to a multiprecision
integral type, similar to those in
[Boost.Multiprecision](https://www.boost.org/doc/libs/develop/libs/multiprecision/doc/html/index.html).
- A scaling operation or adding a floating point number turns the elements into doubles,
- which voids the no-overflow-guarantee.
+ A scaling operation or adding a floating point number triggers a conversion of the
+ elemental counters into doubles, which voids the no-overflow-guarantee.
*/
template <class Allocator>
class unlimited_storage {
@@ -419,67 +131,65 @@ class unlimited_storage {
std::is_same<typename std::allocator_traits<Allocator>::pointer,
typename std::allocator_traits<Allocator>::value_type*>::value,
"unlimited_storage requires allocator with trivial pointer type");
+ using U8 = std::uint8_t;
+ using U16 = std::uint16_t;
+ using U32 = std::uint32_t;
+ using U64 = std::uint64_t;
public:
+ static constexpr bool has_threading_support = false;
+
using allocator_type = Allocator;
using value_type = double;
- using mp_int = detail::mp_int<
- typename std::allocator_traits<allocator_type>::template rebind_alloc<uint64_t>>;
-
-private:
- using types = mp11::mp_list<uint8_t, uint16_t, uint32_t, uint64_t, mp_int, double>;
-
- template <class T>
- static constexpr char type_index() noexcept {
- return static_cast<char>(mp11::mp_find<types, T>::value);
- }
+ using large_int = detail::large_int<
+ typename std::allocator_traits<allocator_type>::template rebind_alloc<U64>>;
struct buffer_type {
- allocator_type alloc;
- std::size_t size = 0;
- char type = 0;
- void* ptr = nullptr;
+ // cannot be moved outside of scope of unlimited_storage, large_int is dependent type
+ using types = mp11::mp_list<U8, U16, U32, U64, large_int, double>;
+
+ template <class T>
+ static constexpr unsigned type_index() noexcept {
+ return static_cast<unsigned>(mp11::mp_find<types, T>::value);
+ }
template <class F, class... Ts>
- decltype(auto) apply(F&& f, Ts&&... ts) const {
+ decltype(auto) visit(F&& f, Ts&&... ts) const {
// this is intentionally not a switch, the if-chain is faster in benchmarks
- if (type == type_index<uint8_t>())
- return f(static_cast<uint8_t*>(ptr), std::forward<Ts>(ts)...);
- if (type == type_index<uint16_t>())
- return f(static_cast<uint16_t*>(ptr), std::forward<Ts>(ts)...);
- if (type == type_index<uint32_t>())
- return f(static_cast<uint32_t*>(ptr), std::forward<Ts>(ts)...);
- if (type == type_index<uint64_t>())
- return f(static_cast<uint64_t*>(ptr), std::forward<Ts>(ts)...);
- if (type == type_index<mp_int>())
- return f(static_cast<mp_int*>(ptr), std::forward<Ts>(ts)...);
+ if (type == type_index<U8>())
+ return f(static_cast<U8*>(ptr), std::forward<Ts>(ts)...);
+ if (type == type_index<U16>())
+ return f(static_cast<U16*>(ptr), std::forward<Ts>(ts)...);
+ if (type == type_index<U32>())
+ return f(static_cast<U32*>(ptr), std::forward<Ts>(ts)...);
+ if (type == type_index<U64>())
+ return f(static_cast<U64*>(ptr), std::forward<Ts>(ts)...);
+ if (type == type_index<large_int>())
+ return f(static_cast<large_int*>(ptr), std::forward<Ts>(ts)...);
return f(static_cast<double*>(ptr), std::forward<Ts>(ts)...);
}
- buffer_type(allocator_type a = {}) : alloc(std::move(a)) {}
+ buffer_type(const allocator_type& a = {}) : alloc(a) {}
buffer_type(buffer_type&& o) noexcept
- : alloc(std::move(o.alloc)), size(o.size), type(o.type), ptr(o.ptr) {
- o.size = 0;
- o.type = 0;
- o.ptr = nullptr;
- }
+ : alloc(std::move(o.alloc))
+ , size(boost::exchange(o.size, 0))
+ , type(boost::exchange(o.type, 0))
+ , ptr(boost::exchange(o.ptr, nullptr)) {}
buffer_type& operator=(buffer_type&& o) noexcept {
- if (this != &o) {
- using std::swap;
- swap(alloc, o.alloc);
- swap(size, o.size);
- swap(type, o.type);
- swap(ptr, o.ptr);
- }
+ using std::swap;
+ swap(alloc, o.alloc);
+ swap(size, o.size);
+ swap(type, o.type);
+ swap(ptr, o.ptr);
return *this;
}
- buffer_type(const buffer_type& o) : alloc(o.alloc) {
- o.apply([this, &o](auto* otp) {
- using T = detail::remove_cvref_t<decltype(*otp)>;
- this->template make<T>(o.size, otp);
+ buffer_type(const buffer_type& x) : alloc(x.alloc) {
+ x.visit([this, n = x.size](const auto* xp) {
+ using T = std::decay_t<decltype(*xp)>;
+ this->template make<T>(n, xp);
});
}
@@ -493,23 +203,18 @@ private:
void destroy() noexcept {
BOOST_ASSERT((ptr == nullptr) == (size == 0));
if (ptr == nullptr) return;
- apply([this](auto* tp) {
- using T = detail::remove_cvref_t<decltype(*tp)>;
+ visit([this](auto* p) {
+ using T = std::decay_t<decltype(*p)>;
using alloc_type =
typename std::allocator_traits<allocator_type>::template rebind_alloc<T>;
alloc_type a(alloc); // rebind allocator
- detail::destroy_buffer(a, tp, size);
+ detail::buffer_destroy(a, p, this->size);
});
size = 0;
type = 0;
ptr = nullptr;
}
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4244) // possible loss of data
-#endif
-
template <class T>
void make(std::size_t n) {
// note: order of commands is to not leave buffer in invalid state upon throw
@@ -519,7 +224,7 @@ private:
using alloc_type =
typename std::allocator_traits<allocator_type>::template rebind_alloc<T>;
alloc_type a(alloc);
- ptr = detail::create_buffer(a, n); // may throw
+ ptr = detail::buffer_create(a, n); // may throw
}
size = n;
type = type_index<T>();
@@ -528,14 +233,14 @@ private:
template <class T, class U>
void make(std::size_t n, U iter) {
// note: iter may be current ptr, so create new buffer before deleting old buffer
- T* new_ptr = nullptr;
+ void* new_ptr = nullptr;
const auto new_type = type_index<T>();
if (n > 0) {
// rebind allocator
using alloc_type =
typename std::allocator_traits<allocator_type>::template rebind_alloc<T>;
alloc_type a(alloc);
- new_ptr = detail::create_buffer(a, n, iter); // may throw
+ new_ptr = detail::buffer_create(a, n, iter); // may throw
}
destroy();
size = n;
@@ -543,229 +248,204 @@ private:
ptr = new_ptr;
}
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
+ allocator_type alloc;
+ std::size_t size = 0;
+ unsigned type = 0;
+ mutable void* ptr = nullptr;
};
- template <class Buffer>
- class reference_t {
- public:
- reference_t(Buffer* b, std::size_t i) : buffer_(b), idx_(i) {}
+ class reference; // forward declare to make friend of const_reference
- reference_t(const reference_t&) = default;
- reference_t& operator=(const reference_t&) = delete; // references do not rebind
- reference_t& operator=(reference_t&&) = delete; // references do not rebind
+ /// implementation detail
+ class const_reference
+ : detail::partially_ordered<const_reference, const_reference, void> {
+ public:
+ const_reference(buffer_type& b, std::size_t i) noexcept : bref_(b), idx_(i) {
+ BOOST_ASSERT(idx_ < bref_.size);
+ }
- // minimal operators for partial ordering
- bool operator<(reference_t rhs) const { return op<detail::less>(rhs); }
- bool operator>(reference_t rhs) const { return op<detail::greater>(rhs); }
- bool operator==(reference_t rhs) const { return op<detail::equal>(rhs); }
+ const_reference(const const_reference&) noexcept = default;
- // adapted copy from boost/operators.hpp for partial ordering
- friend bool operator<=(reference_t x, reference_t y) { return !(y < x); }
- friend bool operator>=(reference_t x, reference_t y) { return !(y > x); }
- friend bool operator!=(reference_t y, reference_t x) { return !(x == y); }
+ // no assignment for const_references
+ const_reference& operator=(const const_reference&) = delete;
+ const_reference& operator=(const_reference&&) = delete;
- template <class U>
- bool operator<(const U& rhs) const {
- return op<detail::less>(rhs);
+ operator double() const noexcept {
+ return bref_.visit(
+ [this](const auto* p) { return static_cast<double>(p[this->idx_]); });
}
- template <class U>
- bool operator>(const U& rhs) const {
- return op<detail::greater>(rhs);
+ bool operator<(const const_reference& o) const noexcept {
+ return apply_binary<detail::safe_less>(o);
}
- template <class U>
- bool operator==(const U& rhs) const {
- return op<detail::equal>(rhs);
+ bool operator==(const const_reference& o) const noexcept {
+ return apply_binary<detail::safe_equal>(o);
}
- // adapted copy from boost/operators.hpp
template <class U>
- friend bool operator<=(reference_t x, const U& y) {
- if (detail::is_unsigned_integral<U>::value) return !(x > y);
- return (x < y) || (x == y);
- }
- template <class U>
- friend bool operator>=(reference_t x, const U& y) {
- if (detail::is_unsigned_integral<U>::value) return !(x < y);
- return (x > y) || (x == y);
- }
- template <class U>
- friend bool operator>(const U& x, reference_t y) {
- return y < x;
- }
- template <class U>
- friend bool operator<(const U& x, reference_t y) {
- return y > x;
- }
- template <class U>
- friend bool operator<=(const U& x, reference_t y) {
- if (detail::is_unsigned_integral<U>::value) return !(y < x);
- return (y > x) || (y == x);
- }
- template <class U>
- friend bool operator>=(const U& x, reference_t y) {
- if (detail::is_unsigned_integral<U>::value) return !(y > x);
- return (y < x) || (y == x);
- }
- template <class U>
- friend bool operator==(const U& y, reference_t x) {
- return x == y;
- }
- template <class U>
- friend bool operator!=(const U& y, reference_t x) {
- return !(x == y);
+ detail::if_arithmetic_or_large_int<U, bool> operator<(const U& o) const noexcept {
+ return apply_binary<detail::safe_less>(o);
}
+
template <class U>
- friend bool operator!=(reference_t y, const U& x) {
- return !(y == x);
+ detail::if_arithmetic_or_large_int<U, bool> operator>(const U& o) const noexcept {
+ return apply_binary<detail::safe_greater>(o);
}
- operator double() const {
- return buffer_->apply(
- [this](const auto* tp) { return static_cast<double>(tp[idx_]); });
+ template <class U>
+ detail::if_arithmetic_or_large_int<U, bool> operator==(const U& o) const noexcept {
+ return apply_binary<detail::safe_equal>(o);
}
- protected:
- template <class Binary, class U>
- bool op(const reference_t<U>& rhs) const {
- const auto i = idx_;
- const auto j = rhs.idx_;
- return buffer_->apply([i, j, &rhs](const auto* ptr) {
- const auto& pi = ptr[i];
- return rhs.buffer_->apply([&pi, j](const auto* q) { return Binary()(pi, q[j]); });
+ private:
+ template <class Binary>
+ bool apply_binary(const const_reference& x) const noexcept {
+ return x.bref_.visit([this, ix = x.idx_](const auto* xp) {
+ return this->apply_binary<Binary>(xp[ix]);
});
}
template <class Binary, class U>
- bool op(const U& rhs) const {
- const auto i = idx_;
- return buffer_->apply([i, &rhs](const auto* tp) { return Binary()(tp[i], rhs); });
+ bool apply_binary(const U& x) const noexcept {
+ return bref_.visit([i = idx_, &x](const auto* p) { return Binary()(p[i], x); });
}
- template <class U>
- friend class reference_t;
-
- Buffer* buffer_;
+ protected:
+ buffer_type& bref_;
std::size_t idx_;
+ friend class reference;
};
-public:
- using const_reference = reference_t<const buffer_type>;
-
- class reference : public reference_t<buffer_type> {
- using base_type = reference_t<buffer_type>;
-
+ /// implementation detail
+ class reference : public const_reference,
+ public detail::partially_ordered<reference, reference, void> {
public:
- using base_type::base_type;
+ reference(buffer_type& b, std::size_t i) noexcept : const_reference(b, i) {}
- reference operator=(reference t) {
- t.buffer_->apply([this, &t](const auto* otp) { *this = otp[t.idx_]; });
- return *this;
+ // references do copy-construct
+ reference(const reference& x) noexcept = default;
+
+ // references do not rebind, assign through
+ reference& operator=(const reference& x) {
+ return operator=(static_cast<const_reference>(x));
}
- reference operator=(const_reference t) {
- t.buffer_->apply([this, &t](const auto* otp) { *this = otp[t.idx_]; });
+ // references do not rebind, assign through
+ reference& operator=(const const_reference& x) {
+ // safe for self-assignment, assigning matching type doesn't invalide buffer
+ x.bref_.visit([this, ix = x.idx_](const auto* xp) { this->operator=(xp[ix]); });
return *this;
}
template <class U>
- reference operator=(const U& t) {
- base_type::buffer_->apply([this, &t](auto* tp) {
- tp[this->idx_] = 0;
- adder()(tp, *(this->buffer_), this->idx_, t);
+ detail::if_arithmetic_or_large_int<U, reference&> operator=(const U& x) {
+ this->bref_.visit([this, &x](auto* p) {
+ // gcc-8 optimizes the expression `p[this->idx_] = 0` away even at -O0,
+ // so we merge it into the next line which is properly counted
+ adder()((p[this->idx_] = 0, p), this->bref_, this->idx_, x);
});
return *this;
}
+ bool operator<(const reference& o) const noexcept {
+ return const_reference::operator<(o);
+ }
+
+ bool operator==(const reference& o) const noexcept {
+ return const_reference::operator==(o);
+ }
+
template <class U>
- reference operator+=(const U& t) {
- base_type::buffer_->apply(adder(), *base_type::buffer_, base_type::idx_, t);
- return *this;
+ detail::if_arithmetic_or_large_int<U, bool> operator<(const U& o) const noexcept {
+ return const_reference::operator<(o);
}
template <class U>
- reference operator*=(const U& t) {
- base_type::buffer_->apply(multiplier(), *base_type::buffer_, base_type::idx_, t);
- return *this;
+ detail::if_arithmetic_or_large_int<U, bool> operator>(const U& o) const noexcept {
+ return const_reference::operator>(o);
}
template <class U>
- reference operator-=(const U& t) {
- return operator+=(-t);
+ detail::if_arithmetic_or_large_int<U, bool> operator==(const U& o) const noexcept {
+ return const_reference::operator==(o);
+ }
+
+ reference& operator+=(const const_reference& x) {
+ x.bref_.visit([this, ix = x.idx_](const auto* xp) { this->operator+=(xp[ix]); });
+ return *this;
}
template <class U>
- reference operator/=(const U& t) {
- return operator*=(1.0 / static_cast<double>(t));
+ detail::if_arithmetic_or_large_int<U, reference&> operator+=(const U& x) {
+ this->bref_.visit(adder(), this->bref_, this->idx_, x);
+ return *this;
}
- reference operator++() {
- base_type::buffer_->apply(incrementor(), *base_type::buffer_, base_type::idx_);
+ reference& operator-=(const double x) { return operator+=(-x); }
+
+ reference& operator*=(const double x) {
+ this->bref_.visit(multiplier(), this->bref_, this->idx_, x);
return *this;
}
- // minimal operators for partial ordering
- bool operator<(reference rhs) const { return base_type::operator<(rhs); }
- bool operator>(reference rhs) const { return base_type::operator>(rhs); }
- bool operator==(reference rhs) const { return base_type::operator==(rhs); }
+ reference& operator/=(const double x) { return operator*=(1.0 / x); }
- // adapted copy from boost/operators.hpp for partial ordering
- friend bool operator<=(reference x, reference y) { return !(y < x); }
- friend bool operator>=(reference x, reference y) { return !(y > x); }
- friend bool operator!=(reference y, reference x) { return !(x == y); }
+ reference& operator++() {
+ this->bref_.visit(incrementor(), this->bref_, this->idx_);
+ return *this;
+ }
};
private:
- template <class Value, class Reference, class Buffer>
- class iterator_t
- : public boost::iterator_adaptor<iterator_t<Value, Reference, Buffer>, std::size_t,
- Value, std::random_access_iterator_tag, Reference,
- std::ptrdiff_t> {
-
+ template <class Value, class Reference>
+ class iterator_impl : public detail::iterator_adaptor<iterator_impl<Value, Reference>,
+ std::size_t, Reference, Value> {
public:
- iterator_t() = default;
- template <class V, class R, class B>
- iterator_t(const iterator_t<V, R, B>& it)
- : iterator_t::iterator_adaptor_(it.base()), buffer_(it.buffer_) {}
- iterator_t(Buffer* b, std::size_t i) noexcept
- : iterator_t::iterator_adaptor_(i), buffer_(b) {}
+ iterator_impl() = default;
+ template <class V, class R>
+ iterator_impl(const iterator_impl<V, R>& it)
+ : iterator_impl::iterator_adaptor_(it.base()), buffer_(it.buffer_) {}
+ iterator_impl(buffer_type* b, std::size_t i) noexcept
+ : iterator_impl::iterator_adaptor_(i), buffer_(b) {}
- protected:
- template <class V, class R, class B>
- bool equal(const iterator_t<V, R, B>& rhs) const noexcept {
- return buffer_ == rhs.buffer_ && this->base() == rhs.base();
- }
- Reference dereference() const { return {buffer_, this->base()}; }
+ Reference operator*() const noexcept { return {*buffer_, this->base()}; }
- friend class ::boost::iterator_core_access;
- template <class V, class R, class B>
- friend class iterator_t;
+ template <class V, class R>
+ friend class iterator_impl;
private:
- Buffer* buffer_ = nullptr;
+ mutable buffer_type* buffer_ = nullptr;
};
public:
- using const_iterator = iterator_t<const value_type, const_reference, const buffer_type>;
- using iterator = iterator_t<value_type, reference, buffer_type>;
+ using const_iterator = iterator_impl<const value_type, const_reference>;
+ using iterator = iterator_impl<value_type, reference>;
- explicit unlimited_storage(allocator_type a = {}) : buffer(std::move(a)) {}
+ explicit unlimited_storage(const allocator_type& a = {}) : buffer_(a) {}
unlimited_storage(const unlimited_storage&) = default;
unlimited_storage& operator=(const unlimited_storage&) = default;
unlimited_storage(unlimited_storage&&) = default;
unlimited_storage& operator=(unlimited_storage&&) = default;
- template <class T>
- unlimited_storage(const storage_adaptor<T>& s) {
- using V = detail::remove_cvref_t<decltype(s[0])>;
- constexpr auto ti = type_index<V>();
- detail::static_if_c<(ti < mp11::mp_size<types>::value)>(
- [&](auto) { buffer.template make<V>(s.size(), s.begin()); },
- [&](auto) { buffer.template make<double>(s.size(), s.begin()); }, 0);
+ // TODO
+ // template <class Allocator>
+ // unlimited_storage(const unlimited_storage<Allocator>& s)
+
+ template <class Iterable, class = detail::requires_iterable<Iterable>>
+ explicit unlimited_storage(const Iterable& s) {
+ using std::begin;
+ using std::end;
+ auto s_begin = begin(s);
+ auto s_end = end(s);
+ using V = typename std::iterator_traits<decltype(begin(s))>::value_type;
+ constexpr auto ti = buffer_type::template type_index<V>();
+ constexpr auto nt = mp11::mp_size<typename buffer_type::types>::value;
+ const std::size_t size = static_cast<std::size_t>(std::distance(s_begin, s_end));
+ detail::static_if_c<(ti < nt)>(
+ [this, &size, &s_begin](auto) { buffer_.template make<V>(size, s_begin); },
+ [this, &size, &s_begin](auto) { buffer_.template make<double>(size, s_begin); },
+ 0);
}
template <class Iterable, class = detail::requires_iterable<Iterable>>
@@ -774,147 +454,156 @@ public:
return *this;
}
- allocator_type get_allocator() const { return buffer.alloc; }
+ allocator_type get_allocator() const { return buffer_.alloc; }
- void reset(std::size_t s) { buffer.template make<uint8_t>(s); }
+ void reset(std::size_t n) { buffer_.template make<U8>(n); }
- std::size_t size() const noexcept { return buffer.size; }
+ std::size_t size() const noexcept { return buffer_.size; }
- reference operator[](std::size_t i) noexcept { return {&buffer, i}; }
- const_reference operator[](std::size_t i) const noexcept { return {&buffer, i}; }
+ reference operator[](std::size_t i) noexcept { return {buffer_, i}; }
+ const_reference operator[](std::size_t i) const noexcept { return {buffer_, i}; }
- bool operator==(const unlimited_storage& o) const noexcept {
- if (size() != o.size()) return false;
- return buffer.apply([&o](const auto* ptr) {
- return o.buffer.apply([ptr, &o](const auto* optr) {
- return std::equal(ptr, ptr + o.size(), optr, detail::equal{});
+ bool operator==(const unlimited_storage& x) const noexcept {
+ if (size() != x.size()) return false;
+ return buffer_.visit([&x](const auto* p) {
+ return x.buffer_.visit([p, n = x.size()](const auto* xp) {
+ return std::equal(p, p + n, xp, detail::safe_equal{});
});
});
}
- template <class T>
- bool operator==(const T& o) const {
- if (size() != o.size()) return false;
- return buffer.apply([&o](const auto* ptr) {
- return std::equal(ptr, ptr + o.size(), std::begin(o), detail::equal{});
+ template <class Iterable>
+ bool operator==(const Iterable& iterable) const {
+ if (size() != iterable.size()) return false;
+ return buffer_.visit([&iterable](const auto* p) {
+ return std::equal(p, p + iterable.size(), std::begin(iterable),
+ detail::safe_equal{});
});
}
unlimited_storage& operator*=(const double x) {
- buffer.apply(multiplier(), buffer, x);
+ buffer_.visit(multiplier(), buffer_, x);
return *this;
}
- iterator begin() noexcept { return {&buffer, 0}; }
- iterator end() noexcept { return {&buffer, size()}; }
- const_iterator begin() const noexcept { return {&buffer, 0}; }
- const_iterator end() const noexcept { return {&buffer, size()}; }
+ iterator begin() noexcept { return {&buffer_, 0}; }
+ iterator end() noexcept { return {&buffer_, size()}; }
+ const_iterator begin() const noexcept { return {&buffer_, 0}; }
+ const_iterator end() const noexcept { return {&buffer_, size()}; }
- /// @private used by unit tests, not part of generic storage interface
+ /// implementation detail; used by unit tests, not part of generic storage interface
template <class T>
- unlimited_storage(std::size_t s, const T* p, allocator_type a = {})
- : buffer(std::move(a)) {
- buffer.template make<T>(s, p);
+ unlimited_storage(std::size_t s, const T* p, const allocator_type& a = {})
+ : buffer_(std::move(a)) {
+ buffer_.template make<T>(s, p);
}
- template <class Archive>
- void serialize(Archive&, unsigned);
-
private:
struct incrementor {
- template <class T, class Buffer>
- void operator()(T* tp, Buffer& b, std::size_t i) {
+ template <class T>
+ void operator()(T* tp, buffer_type& b, std::size_t i) {
+ BOOST_ASSERT(tp && i < b.size);
if (!detail::safe_increment(tp[i])) {
- using U = mp11::mp_at_c<types, (type_index<T>() + 1)>;
+ using U = detail::next_type<typename buffer_type::types, T>;
b.template make<U>(b.size, tp);
++static_cast<U*>(b.ptr)[i];
}
}
- template <class Buffer>
- void operator()(mp_int* tp, Buffer&, std::size_t i) {
- ++tp[i];
- }
+ void operator()(large_int* tp, buffer_type&, std::size_t i) { ++tp[i]; }
- template <class Buffer>
- void operator()(double* tp, Buffer&, std::size_t i) {
- ++tp[i];
- }
+ void operator()(double* tp, buffer_type&, std::size_t i) { ++tp[i]; }
};
struct adder {
- template <class Buffer, class U>
- void operator()(double* tp, Buffer&, std::size_t i, const U& x) {
+ template <class U>
+ void operator()(double* tp, buffer_type&, std::size_t i, const U& x) {
tp[i] += static_cast<double>(x);
}
- template <class T, class Buffer, class U>
- void operator()(T* tp, Buffer& b, std::size_t i, const U& x) {
- U_is_integral(std::is_integral<U>{}, tp, b, i, x);
+ void operator()(large_int* tp, buffer_type&, std::size_t i, const large_int& x) {
+ tp[i] += x; // potentially adding large_int to itself is safe
}
- template <class T, class Buffer, class U>
- void U_is_integral(std::false_type, T* tp, Buffer& b, std::size_t i, const U& x) {
+ template <class T, class U>
+ void operator()(T* tp, buffer_type& b, std::size_t i, const U& x) {
+ is_x_integral(std::is_integral<U>{}, tp, b, i, x);
+ }
+
+ template <class T, class U>
+ void is_x_integral(std::false_type, T* tp, buffer_type& b, std::size_t i,
+ const U& x) {
+ // x could be reference to buffer we manipulate, make copy before changing buffer
+ const auto v = static_cast<double>(x);
b.template make<double>(b.size, tp);
- operator()(static_cast<double*>(b.ptr), b, i, x);
+ operator()(static_cast<double*>(b.ptr), b, i, v);
+ }
+
+ template <class T>
+ void is_x_integral(std::false_type, T* tp, buffer_type& b, std::size_t i,
+ const large_int& x) {
+ // x could be reference to buffer we manipulate, make copy before changing buffer
+ const auto v = static_cast<large_int>(x);
+ b.template make<large_int>(b.size, tp);
+ operator()(static_cast<large_int*>(b.ptr), b, i, v);
}
- template <class T, class Buffer, class U>
- void U_is_integral(std::true_type, T* tp, Buffer& b, std::size_t i, const U& x) {
- U_is_unsigned_integral(std::is_unsigned<U>{}, tp, b, i, x);
+ template <class T, class U>
+ void is_x_integral(std::true_type, T* tp, buffer_type& b, std::size_t i, const U& x) {
+ is_x_unsigned(std::is_unsigned<U>{}, tp, b, i, x);
}
- template <class T, class Buffer, class U>
- void U_is_unsigned_integral(std::false_type, T* tp, Buffer& b, std::size_t i,
- const U& x) {
+ template <class T, class U>
+ void is_x_unsigned(std::false_type, T* tp, buffer_type& b, std::size_t i,
+ const U& x) {
if (x >= 0)
- U_is_unsigned_integral(std::true_type{}, tp, b, i, detail::make_unsigned(x));
+ is_x_unsigned(std::true_type{}, tp, b, i, detail::make_unsigned(x));
else
- U_is_integral(std::false_type{}, tp, b, i, static_cast<double>(x));
+ is_x_integral(std::false_type{}, tp, b, i, static_cast<double>(x));
}
- template <class Buffer, class U>
- void U_is_unsigned_integral(std::true_type, mp_int* tp, Buffer&, std::size_t i,
- const U& x) {
- tp[i] += x;
+ template <class T, class U>
+ void is_x_unsigned(std::true_type, T* tp, buffer_type& b, std::size_t i, const U& x) {
+ if (detail::safe_radd(tp[i], x)) return;
+ // x could be reference to buffer we manipulate, need to convert to value
+ const auto y = x;
+ using TN = detail::next_type<typename buffer_type::types, T>;
+ b.template make<TN>(b.size, tp);
+ is_x_unsigned(std::true_type{}, static_cast<TN*>(b.ptr), b, i, y);
}
- template <class T, class Buffer, class U>
- void U_is_unsigned_integral(std::true_type, T* tp, Buffer& b, std::size_t i,
- const U& x) {
- if (detail::safe_radd(tp[i], x)) return;
- using V = mp11::mp_at_c<types, (type_index<T>() + 1)>;
- b.template make<V>(b.size, tp);
- U_is_unsigned_integral(std::true_type{}, static_cast<V*>(b.ptr), b, i, x);
+ template <class U>
+ void is_x_unsigned(std::true_type, large_int* tp, buffer_type&, std::size_t i,
+ const U& x) {
+ tp[i] += x;
}
};
struct multiplier {
- template <class T, class Buffer>
- void operator()(T* tp, Buffer& b, const double x) {
+ template <class T>
+ void operator()(T* tp, buffer_type& b, const double x) {
// potential lossy conversion that cannot be avoided
b.template make<double>(b.size, tp);
operator()(static_cast<double*>(b.ptr), b, x);
}
- template <class Buffer>
- void operator()(double* tp, Buffer& b, const double x) {
+ void operator()(double* tp, buffer_type& b, const double x) {
for (auto end = tp + b.size; tp != end; ++tp) *tp *= x;
}
- template <class T, class Buffer, class U>
- void operator()(T* tp, Buffer& b, std::size_t i, const U& x) {
+ template <class T>
+ void operator()(T* tp, buffer_type& b, std::size_t i, const double x) {
b.template make<double>(b.size, tp);
operator()(static_cast<double*>(b.ptr), b, i, x);
}
- template <class Buffer, class U>
- void operator()(double* tp, Buffer&, std::size_t i, const U& x) {
+ void operator()(double* tp, buffer_type&, std::size_t i, const double x) {
tp[i] *= static_cast<double>(x);
}
};
- buffer_type buffer;
+ mutable buffer_type buffer_;
+ friend struct unsafe_access;
};
} // namespace histogram
diff --git a/boost/histogram/unsafe_access.hpp b/boost/histogram/unsafe_access.hpp
index 9cff0ea99e..4a39965373 100644
--- a/boost/histogram/unsafe_access.hpp
+++ b/boost/histogram/unsafe_access.hpp
@@ -13,7 +13,18 @@
namespace boost {
namespace histogram {
-/// Unsafe read/write access to classes that potentially break consistency
+/** Unsafe read/write access to private data that potentially breaks consistency.
+
+ This struct enables access to private data of some classes. It is intended for library
+ developers who need this to implement algorithms efficiently, for example,
+ serialization. Users should not use this. If you are a user who absolutely needs this to
+ get a specific effect, please submit an issue on Github. Perhaps the public
+ interface is insufficient and should be extended for your use case.
+
+ Unlike the normal interface, the unsafe_access interface may change between versions.
+ If your code relies on unsafe_access, it may or may not break when you update Boost.
+ This is another reason to not use it unless you are ok with these conditions.
+*/
struct unsafe_access {
/**
Get axes.
@@ -58,13 +69,31 @@ struct unsafe_access {
*/
template <class Histogram>
static auto& storage(Histogram& hist) {
- return hist.storage_;
+ return hist.storage_and_mutex_.first();
}
/// @copydoc storage()
template <class Histogram>
static const auto& storage(const Histogram& hist) {
- return hist.storage_;
+ return hist.storage_and_mutex_.first();
+ }
+
+ /**
+ Get buffer of unlimited_storage.
+ @param storage instance of unlimited_storage.
+ */
+ template <class Allocator>
+ static constexpr auto& unlimited_storage_buffer(unlimited_storage<Allocator>& storage) {
+ return storage.buffer_;
+ }
+
+ /**
+ Get implementation of storage_adaptor.
+ @param storage instance of storage_adaptor.
+ */
+ template <class T>
+ static constexpr auto& storage_adaptor_impl(storage_adaptor<T>& storage) {
+ return static_cast<typename storage_adaptor<T>::impl_type&>(storage);
}
};
diff --git a/boost/interprocess/detail/os_file_functions.hpp b/boost/interprocess/detail/os_file_functions.hpp
index 7a41868188..0eeb26e2bc 100644
--- a/boost/interprocess/detail/os_file_functions.hpp
+++ b/boost/interprocess/detail/os_file_functions.hpp
@@ -543,7 +543,7 @@ inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
int ret = ::fcntl(hnd, F_SETLK, &lock);
if(ret == -1){
return (errno == EAGAIN || errno == EACCES) ?
- acquired = false, true : false;
+ (acquired = false, true) : false;
}
return (acquired = true);
}
@@ -578,7 +578,7 @@ inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
int ret = ::fcntl(hnd, F_SETLK, &lock);
if(ret == -1){
return (errno == EAGAIN || errno == EACCES) ?
- acquired = false, true : false;
+ (acquired = false, true) : false;
}
return (acquired = true);
}
diff --git a/boost/interprocess/detail/win32_api.hpp b/boost/interprocess/detail/win32_api.hpp
index bf0c683185..476171380b 100644
--- a/boost/interprocess/detail/win32_api.hpp
+++ b/boost/interprocess/detail/win32_api.hpp
@@ -1862,10 +1862,10 @@ class c_heap_deleter
void realloc_mem(std::size_t num_bytes)
{
- void *buf = ::realloc(m_buf, num_bytes);
- if(!buf){
- free(m_buf);
- m_buf = 0;
+ void *oldBuf = m_buf;
+ m_buf = ::realloc(m_buf, num_bytes);
+ if (!m_buf){
+ free(oldBuf);
}
}
diff --git a/boost/interprocess/streams/bufferstream.hpp b/boost/interprocess/streams/bufferstream.hpp
index 3690128fe2..1a529627c8 100644
--- a/boost/interprocess/streams/bufferstream.hpp
+++ b/boost/interprocess/streams/bufferstream.hpp
@@ -238,7 +238,7 @@ class basic_bufferbuf
return pos_type(off_type(-1));
else {
this->setp(this->pbase(), this->pbase() + n);
- this->pbump(off);
+ this->pbump(static_cast<int>(off));
}
}
diff --git a/boost/intrusive/detail/workaround.hpp b/boost/intrusive/detail/workaround.hpp
index a9e157077a..f0cfaf2b2d 100644
--- a/boost/intrusive/detail/workaround.hpp
+++ b/boost/intrusive/detail/workaround.hpp
@@ -23,6 +23,11 @@
#include <boost/config.hpp>
#endif
+// MSVC-12 ICEs when variadic templates are enabled.
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && (!defined(BOOST_MSVC) || BOOST_MSVC >= 1900)
+ #define BOOST_INTRUSIVE_VARIADIC_TEMPLATES
+#endif
+
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_INTRUSIVE_PERFECT_FORWARDING
#endif
diff --git a/boost/intrusive/pack_options.hpp b/boost/intrusive/pack_options.hpp
index 944243f661..ff07678fff 100644
--- a/boost/intrusive/pack_options.hpp
+++ b/boost/intrusive/pack_options.hpp
@@ -209,6 +209,12 @@ struct do_pack<typelist<Prev, Last> >
typedef typename Prev::template pack<Last> type;
};
+template<class ...Others>
+struct do_pack<typelist<void, Others...> >
+{
+ typedef typename do_pack<typelist<Others...> >::type type;
+};
+
template<class Prev, class ...Others>
struct do_pack<typelist<Prev, Others...> >
{
diff --git a/boost/intrusive/treap.hpp b/boost/intrusive/treap.hpp
index 56569757c8..d5e3c0ce8a 100644
--- a/boost/intrusive/treap.hpp
+++ b/boost/intrusive/treap.hpp
@@ -82,7 +82,7 @@ struct treap_tag;
//! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<>,
-//! \c compare<> and \c priority_compare<>
+//! \c compare<>, \c priority<> and \c priority_of_value<>
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
diff --git a/boost/intrusive/treap_set.hpp b/boost/intrusive/treap_set.hpp
index 6c0ea3b643..31d0f6a039 100644
--- a/boost/intrusive/treap_set.hpp
+++ b/boost/intrusive/treap_set.hpp
@@ -41,7 +41,7 @@ class treap_multiset_impl;
//! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<>,
-//! \c compare<> and \c priority_compare<>
+//! \c compare<>, \c priority<> and \c priority_of_value<>
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
@@ -600,7 +600,7 @@ class treap_set
//! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<>,
-//! \c compare<> and \c priority_compare<>
+//! \c compare<>, \c priority<> and \c priority_of_value<>
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
diff --git a/boost/iostreams/detail/adapter/concept_adapter.hpp b/boost/iostreams/detail/adapter/concept_adapter.hpp
index 05b5ff4ca7..3a76b3fb38 100644
--- a/boost/iostreams/detail/adapter/concept_adapter.hpp
+++ b/boost/iostreams/detail/adapter/concept_adapter.hpp
@@ -117,8 +117,8 @@ public:
std::streamsize optimal_buffer_size() const
{ return iostreams::optimal_buffer_size(t_); }
-public:
- concept_adapter& operator=(const concept_adapter&);
+private:
+ BOOST_DELETED_FUNCTION(concept_adapter& operator=(const concept_adapter&));
value_type t_;
};
diff --git a/boost/iostreams/detail/functional.hpp b/boost/iostreams/detail/functional.hpp
index 97b7fe5e75..e4b4a98b89 100644
--- a/boost/iostreams/detail/functional.hpp
+++ b/boost/iostreams/detail/functional.hpp
@@ -38,7 +38,7 @@ public:
{ }
void operator()() const { boost::iostreams::close(t_, which_); }
private:
- device_close_operation& operator=(const device_close_operation&);
+ BOOST_DELETED_FUNCTION(device_close_operation& operator=(const device_close_operation&));
T& t_;
BOOST_IOS::openmode which_;
};
@@ -52,7 +52,7 @@ public:
{ }
void operator()() const { boost::iostreams::close(t_, snk_, which_); }
private:
- filter_close_operation& operator=(const filter_close_operation&);
+ BOOST_DELETED_FUNCTION(filter_close_operation& operator=(const filter_close_operation&));
T& t_;
Sink& snk_;
BOOST_IOS::openmode which_;
@@ -78,7 +78,7 @@ public:
device_close_all_operation(T& t) : t_(t) { }
void operator()() const { detail::close_all(t_); }
private:
- device_close_all_operation& operator=(const device_close_all_operation&);
+ BOOST_DELETED_FUNCTION(device_close_all_operation& operator=(const device_close_all_operation&));
T& t_;
};
@@ -89,7 +89,7 @@ public:
filter_close_all_operation(T& t, Sink& snk) : t_(t), snk_(snk) { }
void operator()() const { detail::close_all(t_, snk_); }
private:
- filter_close_all_operation& operator=(const filter_close_all_operation&);
+ BOOST_DELETED_FUNCTION(filter_close_all_operation& operator=(const filter_close_all_operation&));
T& t_;
Sink& snk_;
};
@@ -115,7 +115,7 @@ public:
{ }
void operator()() const { t_.close(which_); }
private:
- member_close_operation& operator=(const member_close_operation&);
+ BOOST_DELETED_FUNCTION(member_close_operation& operator=(const member_close_operation&));
T& t_;
BOOST_IOS::openmode which_;
};
@@ -133,7 +133,7 @@ public:
reset_operation(T& t) : t_(t) { }
void operator()() const { t_.reset(); }
private:
- reset_operation& operator=(const reset_operation&);
+ BOOST_DELETED_FUNCTION(reset_operation& operator=(const reset_operation&));
T& t_;
};
@@ -149,7 +149,7 @@ public:
clear_flags_operation(T& t) : t_(t) { }
void operator()() const { t_ = 0; }
private:
- clear_flags_operation& operator=(const clear_flags_operation&);
+ BOOST_DELETED_FUNCTION(clear_flags_operation& operator=(const clear_flags_operation&));
T& t_;
};
@@ -173,7 +173,7 @@ public:
buf_.flush(dev_);
}
private:
- flush_buffer_operation& operator=(const flush_buffer_operation&);
+ BOOST_DELETED_FUNCTION(flush_buffer_operation& operator=(const flush_buffer_operation&));
Buffer& buf_;
Device& dev_;
bool flush_;
diff --git a/boost/iostreams/filter/bzip2.hpp b/boost/iostreams/filter/bzip2.hpp
index 249e43a04f..a468e05804 100644
--- a/boost/iostreams/filter/bzip2.hpp
+++ b/boost/iostreams/filter/bzip2.hpp
@@ -365,22 +365,24 @@ bool bzip2_decompressor_impl<Alloc>::filter
( const char*& src_begin, const char* src_end,
char*& dest_begin, char* dest_end, bool flush )
{
- if (eof_) {
- // reset the stream if there are more characters
- if(src_begin == src_end)
- return false;
- else
- close();
- }
- if (!ready())
- init();
- before(src_begin, src_end, dest_begin, dest_end);
- int result = decompress();
- if(result == bzip2::ok && flush)
- result = check_end(src_begin, dest_begin);
- after(src_begin, dest_begin);
- bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result);
- eof_ = result == bzip2::stream_end;
+ do {
+ if (eof_) {
+ // reset the stream if there are more characters
+ if(src_begin == src_end)
+ return false;
+ else
+ close();
+ }
+ if (!ready())
+ init();
+ before(src_begin, src_end, dest_begin, dest_end);
+ int result = decompress();
+ if(result == bzip2::ok && flush)
+ result = check_end(src_begin, dest_begin);
+ after(src_begin, dest_begin);
+ bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result);
+ eof_ = result == bzip2::stream_end;
+ } while (eof_ && src_begin != src_end && dest_begin != dest_end);
return true;
}
diff --git a/boost/iostreams/filter/lzma.hpp b/boost/iostreams/filter/lzma.hpp
index 94cd2b3b54..858474c011 100644
--- a/boost/iostreams/filter/lzma.hpp
+++ b/boost/iostreams/filter/lzma.hpp
@@ -87,10 +87,12 @@ const int null = 0;
struct lzma_params {
// Non-explicit constructor.
- lzma_params( uint32_t level = lzma::default_compression )
+ lzma_params( uint32_t level = lzma::default_compression, uint32_t threads = 1 )
: level(level)
+ , threads(threads)
{ }
uint32_t level;
+ uint32_t threads;
};
//
@@ -170,8 +172,10 @@ private:
lzma::alloc_func,
lzma::free_func,
void* derived );
- void* stream_; // Actual type: lzmadec_stream*.
- uint32_t level;
+ void init_stream(bool compress);
+ void* stream_; // Actual type: lzma_stream*.
+ uint32_t level_;
+ uint32_t threads_;
};
//
@@ -182,7 +186,7 @@ private:
template<typename Alloc = std::allocator<char> >
class lzma_compressor_impl : public lzma_base, public lzma_allocator<Alloc> {
public:
- lzma_compressor_impl(const lzma_params& = lzma::default_compression);
+ lzma_compressor_impl(const lzma_params& = lzma_params());
~lzma_compressor_impl();
bool filter( const char*& src_begin, const char* src_end,
char*& dest_begin, char* dest_end, bool flush );
@@ -222,7 +226,7 @@ private:
public:
typedef typename base_type::char_type char_type;
typedef typename base_type::category category;
- basic_lzma_compressor( const lzma_params& = lzma::default_compression,
+ basic_lzma_compressor( const lzma_params& = lzma_params(),
std::streamsize buffer_size = default_device_buffer_size );
};
BOOST_IOSTREAMS_PIPABLE(basic_lzma_compressor, 1)
diff --git a/boost/lockfree/policies.hpp b/boost/lockfree/policies.hpp
index cf43ad22f3..479411eabb 100644
--- a/boost/lockfree/policies.hpp
+++ b/boost/lockfree/policies.hpp
@@ -9,7 +9,7 @@
#ifndef BOOST_LOCKFREE_POLICIES_HPP_INCLUDED
#define BOOST_LOCKFREE_POLICIES_HPP_INCLUDED
-#include <boost/parameter/aux_/template_keyword.hpp>
+#include <boost/parameter/template_keyword.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/size_t.hpp>
diff --git a/boost/lockfree/queue.hpp b/boost/lockfree/queue.hpp
index 808bebd6c5..c8970bbce2 100644
--- a/boost/lockfree/queue.hpp
+++ b/boost/lockfree/queue.hpp
@@ -117,7 +117,7 @@ private:
typedef typename detail::select_tagged_handle<node, node_based>::handle_type handle_type;
node(T const & v, handle_type null_handle):
- data(v)//, next(tagged_node_handle(0, 0))
+ next(tagged_node_handle(null_handle, 0)), data(v)
{
/* increment tag to avoid ABA problem */
tagged_node_handle old_next = next.load(memory_order_relaxed);
diff --git a/boost/log/detail/sink_init_helpers.hpp b/boost/log/detail/sink_init_helpers.hpp
index a3bbe0e8a1..4f0bed850c 100644
--- a/boost/log/detail/sink_init_helpers.hpp
+++ b/boost/log/detail/sink_init_helpers.hpp
@@ -20,9 +20,13 @@
#include <boost/mpl/bool.hpp>
#include <boost/parameter/binding.hpp>
#include <boost/type_traits/is_void.hpp>
+#include <boost/type_traits/is_array.hpp>
#include <boost/core/enable_if.hpp>
-#include <boost/phoenix/core/is_actor.hpp>
+#include <boost/utility/string_view_fwd.hpp>
#include <boost/log/detail/config.hpp>
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+#include <string_view>
+#endif
#include <boost/log/core/core.hpp>
#include <boost/log/expressions/filter.hpp>
#include <boost/log/expressions/formatter.hpp>
@@ -30,6 +34,7 @@
#include <boost/log/utility/setup/formatter_parser.hpp>
#include <boost/log/keywords/filter.hpp>
#include <boost/log/keywords/format.hpp>
+#include <boost/log/detail/is_character_type.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
@@ -44,18 +49,39 @@ namespace aux {
// The function creates a filter functional object from the provided argument
template< typename CharT >
-inline filter acquire_filter(const CharT* filter)
+inline typename boost::enable_if_c<
+ log::aux::is_character_type< CharT >::value,
+ filter
+>::type acquire_filter(const CharT* filter)
{
return boost::log::parse_filter(filter);
}
+
template< typename CharT, typename TraitsT, typename AllocatorT >
inline filter acquire_filter(std::basic_string< CharT, TraitsT, AllocatorT > const& filter)
{
return boost::log::parse_filter(filter);
}
+
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+template< typename CharT, typename TraitsT >
+inline filter acquire_filter(std::basic_string_view< CharT, TraitsT > const& filter)
+{
+ const CharT* p = filter.data();
+ return boost::log::parse_filter(p, p + filter.size());
+}
+#endif // !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+
+template< typename CharT, typename TraitsT >
+inline filter acquire_filter(boost::basic_string_view< CharT, TraitsT > const& filter)
+{
+ const CharT* p = filter.data();
+ return boost::log::parse_filter(p, p + filter.size());
+}
+
template< typename FilterT >
-inline typename boost::enable_if_c<
- phoenix::is_actor< FilterT >::value,
+inline typename boost::disable_if_c<
+ boost::is_array< FilterT >::value,
FilterT const&
>::type acquire_filter(FilterT const& filter)
{
@@ -75,20 +101,41 @@ inline void setup_filter(SinkT& s, ArgsT const& args, mpl::false_)
}
-// The function creates a filter functional object from the provided argument
+// The function creates a formatter functional object from the provided argument
template< typename CharT >
-inline basic_formatter< CharT > acquire_formatter(const CharT* formatter)
+inline typename boost::enable_if_c<
+ log::aux::is_character_type< CharT >::value,
+ basic_formatter< CharT >
+>::type acquire_formatter(const CharT* formatter)
{
return boost::log::parse_formatter(formatter);
}
+
template< typename CharT, typename TraitsT, typename AllocatorT >
inline basic_formatter< CharT > acquire_formatter(std::basic_string< CharT, TraitsT, AllocatorT > const& formatter)
{
return boost::log::parse_formatter(formatter);
}
+
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+template< typename CharT, typename TraitsT >
+inline basic_formatter< CharT > acquire_formatter(std::basic_string_view< CharT, TraitsT > const& formatter)
+{
+ const CharT* p = formatter.data();
+ return boost::log::parse_formatter(p, p + formatter.size());
+}
+#endif // !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+
+template< typename CharT, typename TraitsT >
+inline basic_formatter< CharT > acquire_formatter(boost::basic_string_view< CharT, TraitsT > const& formatter)
+{
+ const CharT* p = formatter.data();
+ return boost::log::parse_formatter(p, p + formatter.size());
+}
+
template< typename FormatterT >
-inline typename boost::enable_if_c<
- phoenix::is_actor< FormatterT >::value,
+inline typename boost::disable_if_c<
+ boost::is_array< FormatterT >::value,
FormatterT const&
>::type acquire_formatter(FormatterT const& formatter)
{
diff --git a/boost/log/expressions/formatters.hpp b/boost/log/expressions/formatters.hpp
index f85cb7903b..e61857e1ea 100644
--- a/boost/log/expressions/formatters.hpp
+++ b/boost/log/expressions/formatters.hpp
@@ -31,6 +31,7 @@
#include <boost/log/expressions/formatters/if.hpp>
#include <boost/log/expressions/formatters/wrap_formatter.hpp>
+#include <boost/log/expressions/formatters/auto_newline.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
diff --git a/boost/log/expressions/formatters/auto_newline.hpp b/boost/log/expressions/formatters/auto_newline.hpp
new file mode 100644
index 0000000000..5677314484
--- /dev/null
+++ b/boost/log/expressions/formatters/auto_newline.hpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright Andrey Semashev 2019.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file expressions/formatters/auto_newline.hpp
+ * \author Andrey Semashev
+ * \date 23.06.2019
+ *
+ * The header contains implementation of formatter for inserting a newline, unless there is already one inserted.
+ */
+
+#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_AUTO_NEWLINE_HPP_INCLUDED_
+#define BOOST_LOG_EXPRESSIONS_FORMATTERS_AUTO_NEWLINE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/manipulators/auto_newline.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace expressions {
+
+/*!
+ * Formatter for inserting a newline character, unless the last character
+ * inserted into the stream is already a newline.
+ */
+using boost::log::auto_newline;
+
+} // namespace expressions
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_AUTO_NEWLINE_HPP_INCLUDED_
diff --git a/boost/log/keywords/auto_newline_mode.hpp b/boost/log/keywords/auto_newline_mode.hpp
new file mode 100644
index 0000000000..6b9a04110c
--- /dev/null
+++ b/boost/log/keywords/auto_newline_mode.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2019.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/auto_newline_mode.hpp
+ * \author Andrey Semashev
+ * \date 23.06.2019
+ *
+ * The header contains the \c auto_newline_mode keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_AUTO_NEWLINE_MODE_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_AUTO_NEWLINE_MODE_HPP_INCLUDED_
+
+#include <boost/parameter/keyword.hpp>
+#include <boost/log/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace keywords {
+
+//! The keyword for passing automatic trailing newline insertion mode to a sink backend initialization
+BOOST_PARAMETER_KEYWORD(tag, auto_newline_mode)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_AUTO_NEWLINE_MODE_HPP_INCLUDED_
diff --git a/boost/log/sinks/auto_newline_mode.hpp b/boost/log/sinks/auto_newline_mode.hpp
new file mode 100644
index 0000000000..012b81b180
--- /dev/null
+++ b/boost/log/sinks/auto_newline_mode.hpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright Andrey Semashev 2019.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file sinks/auto_newline_mode.hpp
+ * \author Andrey Semashev
+ * \date 23.06.2019
+ *
+ * The header contains definition of auto-newline modes.
+ */
+
+#ifndef BOOST_LOG_SINKS_AUTO_NEWLINE_MODE_HPP_INCLUDED_HPP_
+#define BOOST_LOG_SINKS_AUTO_NEWLINE_MODE_HPP_INCLUDED_HPP_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+//! The enum lists automatic trailing newline modes
+enum auto_newline_mode
+{
+ disabled_auto_newline, //!< Do not insert automatic trailing newline characters
+ always_insert, //!< Always insert automatic trailing newline characters
+ insert_if_missing //!< Insert automatic trailing newline characters, if not present already
+};
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_AUTO_NEWLINE_MODE_HPP_INCLUDED_HPP_
diff --git a/boost/log/sinks/text_file_backend.hpp b/boost/log/sinks/text_file_backend.hpp
index 486e55a9d7..d72e4cfb53 100644
--- a/boost/log/sinks/text_file_backend.hpp
+++ b/boost/log/sinks/text_file_backend.hpp
@@ -37,9 +37,11 @@
#include <boost/log/keywords/rotation_size.hpp>
#include <boost/log/keywords/time_based_rotation.hpp>
#include <boost/log/keywords/enable_final_rotation.hpp>
+#include <boost/log/keywords/auto_newline_mode.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/light_function.hpp>
#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/sinks/auto_newline_mode.hpp>
#include <boost/log/sinks/basic_sink_backend.hpp>
#include <boost/log/sinks/frontend_requirements.hpp>
#include <boost/log/detail/header.hpp>
@@ -397,6 +399,8 @@ public:
* sink backend destruction. By default, is \c true.
* \li \c auto_flush - Specifies a flag, whether or not to automatically flush the file after each
* written log record. By default, is \c false.
+ * \li \c auto_newline_mode - Specifies automatic trailing newline insertion mode. Must be a value of
+ * the \c auto_newline_mode enum. By default, is <tt>auto_newline_mode::insert_if_missing</tt>.
*
* \note Read the caution note regarding file name pattern in the <tt>sinks::file::collector::scan_for_files</tt>
* documentation.
@@ -513,6 +517,14 @@ public:
BOOST_LOG_API void auto_flush(bool enable = true);
/*!
+ * Selects whether a trailing newline should be automatically inserted after every log record. See
+ * \c auto_newline_mode description for the possible modes of operation.
+ *
+ * \param mode The trailing newline insertion mode.
+ */
+ BOOST_LOG_API void set_auto_newline_mode(auto_newline_mode mode);
+
+ /*!
* \return The name of the currently open log file. If no file is open, returns an empty path.
*/
BOOST_LOG_API filesystem::path get_current_file_name() const;
@@ -566,6 +578,7 @@ private:
args[keywords::open_mode | (std::ios_base::trunc | std::ios_base::out)],
args[keywords::rotation_size | (std::numeric_limits< uintmax_t >::max)()],
args[keywords::time_based_rotation | time_based_rotation_predicate()],
+ args[keywords::auto_newline_mode | insert_if_missing],
args[keywords::auto_flush | false],
args[keywords::enable_final_rotation | true]);
}
@@ -576,6 +589,7 @@ private:
std::ios_base::openmode mode,
uintmax_t rotation_size,
time_based_rotation_predicate const& time_based_rotation,
+ auto_newline_mode auto_newline,
bool auto_flush,
bool enable_final_rotation);
diff --git a/boost/log/sinks/text_multifile_backend.hpp b/boost/log/sinks/text_multifile_backend.hpp
index 8e707b990c..2db672b366 100644
--- a/boost/log/sinks/text_multifile_backend.hpp
+++ b/boost/log/sinks/text_multifile_backend.hpp
@@ -25,7 +25,10 @@
#include <boost/filesystem/path.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/light_function.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
#include <boost/log/detail/cleanup_scope_guard.hpp>
+#include <boost/log/keywords/auto_newline_mode.hpp>
+#include <boost/log/sinks/auto_newline_mode.hpp>
#include <boost/log/sinks/basic_sink_backend.hpp>
#include <boost/log/utility/formatting_ostream.hpp>
#include <boost/log/detail/header.hpp>
@@ -161,11 +164,25 @@ private:
public:
/*!
* Default constructor. The constructed sink backend has no file name composer and
- * thus will not write any files.
+ * thus will not write any files. All other parameters are set to their defaults.
*/
BOOST_LOG_API text_multifile_backend();
/*!
+ * Constructor. Creates a sink backend with the specified named parameters.
+ * The following named parameters are supported:
+ *
+ * \li \c auto_newline_mode - Specifies automatic trailing newline insertion mode. Must be a value of
+ * the \c auto_newline_mode enum. By default, is <tt>auto_newline_mode::insert_if_missing</tt>.
+ */
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(text_multifile_backend, construct)
+#else
+ template< typename... ArgsT >
+ explicit text_multifile_backend(ArgsT... const& args);
+#endif
+
+ /*!
* Destructor
*/
BOOST_LOG_API ~text_multifile_backend();
@@ -182,12 +199,29 @@ public:
}
/*!
+ * Selects whether a trailing newline should be automatically inserted after every log record. See
+ * \c auto_newline_mode description for the possible modes of operation.
+ *
+ * \param mode The trailing newline insertion mode.
+ */
+ BOOST_LOG_API void set_auto_newline_mode(auto_newline_mode mode);
+
+ /*!
* The method writes the message to the sink
*/
BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message);
private:
#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! Constructor implementation
+ template< typename ArgsT >
+ void construct(ArgsT const& args)
+ {
+ construct(args[keywords::auto_newline_mode | insert_if_missing]);
+ }
+ //! Constructor implementation
+ BOOST_LOG_API void construct(auto_newline_mode auto_newline);
+
//! The method sets the file name composer
BOOST_LOG_API void set_file_name_composer_internal(file_name_composer_type const& composer);
#endif // BOOST_LOG_DOXYGEN_PASS
diff --git a/boost/log/sinks/text_ostream_backend.hpp b/boost/log/sinks/text_ostream_backend.hpp
index 9d8ad0d6cd..487c8f8178 100644
--- a/boost/log/sinks/text_ostream_backend.hpp
+++ b/boost/log/sinks/text_ostream_backend.hpp
@@ -18,6 +18,10 @@
#include <ostream>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
+#include <boost/log/keywords/auto_flush.hpp>
+#include <boost/log/keywords/auto_newline_mode.hpp>
+#include <boost/log/sinks/auto_newline_mode.hpp>
#include <boost/log/sinks/basic_sink_backend.hpp>
#include <boost/log/sinks/frontend_requirements.hpp>
#include <boost/log/detail/header.hpp>
@@ -71,6 +75,23 @@ public:
* Constructor. No streams attached to the constructed backend, auto flush feature disabled.
*/
BOOST_LOG_API basic_text_ostream_backend();
+
+ /*!
+ * Constructor. Creates a sink backend with the specified named parameters.
+ * The following named parameters are supported:
+ *
+ * \li \c auto_flush - Specifies a flag, whether or not to automatically flush the attached streams after each
+ * written log record. By default, is \c false.
+ * \li \c auto_newline_mode - Specifies automatic trailing newline insertion mode. Must be a value of
+ * the \c auto_newline_mode enum. By default, is <tt>auto_newline_mode::insert_if_missing</tt>.
+ */
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(basic_text_ostream_backend, construct)
+#else
+ template< typename... ArgsT >
+ explicit basic_text_ostream_backend(ArgsT... const& args);
+#endif
+
/*!
* Destructor
*/
@@ -91,19 +112,43 @@ public:
BOOST_LOG_API void remove_stream(shared_ptr< stream_type > const& strm);
/*!
- * Sets the flag to automatically flush buffers of all attached streams after each log record
+ * Sets the flag to automatically flush buffers of all attached streams after each log record.
+ *
+ * \param enable The flag indicates whether the automatic buffer flush should be performed.
*/
- BOOST_LOG_API void auto_flush(bool f = true);
+ BOOST_LOG_API void auto_flush(bool enable = true);
/*!
- * The method writes the message to the sink
+ * Selects whether a trailing newline should be automatically inserted after every log record. See
+ * \c auto_newline_mode description for the possible modes of operation.
+ *
+ * \param mode The trailing newline insertion mode.
+ */
+ BOOST_LOG_API void set_auto_newline_mode(auto_newline_mode mode);
+
+ /*!
+ * The method writes the message to the sink.
*/
BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message);
/*!
- * The method flushes the associated streams
+ * The method flushes all attached streams.
*/
BOOST_LOG_API void flush();
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ //! Constructor implementation
+ template< typename ArgsT >
+ void construct(ArgsT const& args)
+ {
+ construct(
+ args[keywords::auto_newline_mode | insert_if_missing],
+ args[keywords::auto_flush | false]);
+ }
+ //! Constructor implementation
+ BOOST_LOG_API void construct(auto_newline_mode auto_newline, bool auto_flush);
+#endif // BOOST_LOG_DOXYGEN_PASS
};
#ifdef BOOST_LOG_USE_CHAR
diff --git a/boost/log/sources/record_ostream.hpp b/boost/log/sources/record_ostream.hpp
index 87274a2774..776315ae1f 100644
--- a/boost/log/sources/record_ostream.hpp
+++ b/boost/log/sources/record_ostream.hpp
@@ -51,17 +51,25 @@ namespace aux {
template< typename StreamT, typename T, bool ByValueV, typename R >
struct enable_record_ostream_generic_operator {};
+
template< typename CharT, typename T, typename R >
struct enable_record_ostream_generic_operator< basic_record_ostream< CharT >, T, false, R > :
public boost::disable_if_c< boost::is_scalar< typename boost::remove_cv< T >::type >::value, R >
{
};
+
template< typename CharT, typename T, typename R >
struct enable_record_ostream_generic_operator< basic_record_ostream< CharT >, T, true, R > :
public boost::enable_if_c< boost::is_enum< typename boost::remove_cv< T >::type >::value, R >
{
};
+template< typename CharT, typename T, typename R >
+struct enable_record_ostream_generic_operator< basic_record_ostream< CharT >, T*, true, R > :
+ public disable_if_streamable_char_type< typename boost::remove_cv< T >::type, R >
+{
+};
+
} // namespace aux
/*!
@@ -326,12 +334,6 @@ public:
return *this;
}
- basic_record_ostream& operator<< (const void* value)
- {
- static_cast< base_type& >(*this) << value;
- return *this;
- }
-
basic_record_ostream& operator<< (std::basic_streambuf< char_type, traits_type >* buf)
{
static_cast< base_type& >(*this) << buf;
diff --git a/boost/log/trivial.hpp b/boost/log/trivial.hpp
index ece0c900e6..7fb896ac36 100644
--- a/boost/log/trivial.hpp
+++ b/boost/log/trivial.hpp
@@ -15,6 +15,7 @@
#ifndef BOOST_LOG_TRIVIAL_HPP_INCLUDED_
#define BOOST_LOG_TRIVIAL_HPP_INCLUDED_
+#include <cstddef>
#include <iosfwd>
#include <ostream>
#include <boost/log/detail/config.hpp>
@@ -49,15 +50,26 @@ enum severity_level
};
//! Returns stringized enumeration value or \c NULL, if the value is not valid
-BOOST_LOG_API const char* to_string(severity_level lvl);
+template< typename CharT >
+BOOST_LOG_API const CharT* to_string(severity_level lvl);
+
+//! Returns stringized enumeration value or \c NULL, if the value is not valid
+inline const char* to_string(severity_level lvl)
+{
+ return boost::log::trivial::to_string< char >(lvl);
+}
+
+//! Parses enumeration value from string and returns \c true on success and \c false otherwise
+template< typename CharT >
+BOOST_LOG_API bool from_string(const CharT* str, std::size_t len, severity_level& lvl);
//! Outputs stringized representation of the severity level to the stream
template< typename CharT, typename TraitsT >
inline std::basic_ostream< CharT, TraitsT >& operator<< (
std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)
{
- const char* str = boost::log::trivial::to_string(lvl);
- if (str)
+ const CharT* str = boost::log::trivial::to_string< CharT >(lvl);
+ if (BOOST_LIKELY(!!str))
strm << str;
else
strm << static_cast< int >(lvl);
diff --git a/boost/log/utility/formatting_ostream.hpp b/boost/log/utility/formatting_ostream.hpp
index b39feeb664..e2f83aab0c 100644
--- a/boost/log/utility/formatting_ostream.hpp
+++ b/boost/log/utility/formatting_ostream.hpp
@@ -27,6 +27,9 @@
#include <boost/type_traits/is_scalar.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/log/detail/config.hpp>
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+#include <string_view>
+#endif
#include <boost/log/detail/attachable_sstream_buf.hpp>
#include <boost/log/detail/code_conversion.hpp>
#include <boost/log/utility/string_literal_fwd.hpp>
@@ -45,34 +48,52 @@ namespace aux {
template< typename T, typename R >
struct enable_if_streamable_char_type {};
+template< typename T, typename R >
+struct disable_if_streamable_char_type { typedef R type; };
template< typename R >
struct enable_if_streamable_char_type< char, R > { typedef R type; };
template< typename R >
+struct disable_if_streamable_char_type< char, R > {};
+template< typename R >
struct enable_if_streamable_char_type< wchar_t, R > { typedef R type; };
+template< typename R >
+struct disable_if_streamable_char_type< wchar_t, R > {};
#if !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
#if !defined(BOOST_NO_CXX11_CHAR16_T)
template< typename R >
struct enable_if_streamable_char_type< char16_t, R > { typedef R type; };
+template< typename R >
+struct disable_if_streamable_char_type< char16_t, R > {};
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
template< typename R >
struct enable_if_streamable_char_type< char32_t, R > { typedef R type; };
+template< typename R >
+struct disable_if_streamable_char_type< char32_t, R > {};
#endif
#endif
template< typename StreamT, typename T, bool ByValueV, typename R >
struct enable_formatting_ostream_generic_operator {};
+
template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename R >
struct enable_formatting_ostream_generic_operator< basic_formatting_ostream< CharT, TraitsT, AllocatorT >, T, false, R > :
public boost::disable_if_c< boost::is_scalar< typename boost::remove_cv< T >::type >::value, R >
{
};
+
template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename R >
struct enable_formatting_ostream_generic_operator< basic_formatting_ostream< CharT, TraitsT, AllocatorT >, T, true, R > :
public boost::enable_if_c< boost::is_enum< typename boost::remove_cv< T >::type >::value, R >
{
};
+template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename R >
+struct enable_formatting_ostream_generic_operator< basic_formatting_ostream< CharT, TraitsT, AllocatorT >, T*, true, R > :
+ public disable_if_streamable_char_type< typename boost::remove_cv< T >::type, R >
+{
+};
+
} // namespace aux
/*!
@@ -528,12 +549,6 @@ public:
return *this;
}
- basic_formatting_ostream& operator<< (const void* value)
- {
- m_stream << value;
- return *this;
- }
-
basic_formatting_ostream& operator<< (std::basic_streambuf< char_type, traits_type >* buf)
{
m_stream << buf;
@@ -547,6 +562,15 @@ public:
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+ template< typename OtherCharT, typename OtherTraitsT >
+ friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (basic_formatting_ostream& strm, std::basic_string_view< OtherCharT, OtherTraitsT > const& str)
+ {
+ return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
+ }
+#endif
+
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream& strm, basic_string_literal< OtherCharT, OtherTraitsT > const& str)
@@ -576,6 +600,15 @@ public:
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+ template< typename OtherCharT, typename OtherTraitsT >
+ friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (basic_formatting_ostream& strm, std::basic_string_view< OtherCharT, OtherTraitsT >& str)
+ {
+ return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
+ }
+#endif
+
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream& strm, basic_string_literal< OtherCharT, OtherTraitsT >& str)
@@ -606,6 +639,15 @@ public:
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+ template< typename OtherCharT, typename OtherTraitsT >
+ friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (basic_formatting_ostream&& strm, std::basic_string_view< OtherCharT, OtherTraitsT > const& str)
+ {
+ return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
+ }
+#endif
+
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream&& strm, basic_string_literal< OtherCharT, OtherTraitsT > const& str)
@@ -635,6 +677,15 @@ public:
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+ template< typename OtherCharT, typename OtherTraitsT >
+ friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (basic_formatting_ostream&& strm, std::basic_string_view< OtherCharT, OtherTraitsT >& str)
+ {
+ return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
+ }
+#endif
+
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream&& strm, basic_string_literal< OtherCharT, OtherTraitsT >& str)
@@ -656,7 +707,7 @@ public:
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
-#endif
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
protected:
void init_stream()
diff --git a/boost/log/utility/manipulators.hpp b/boost/log/utility/manipulators.hpp
index cb39fd2416..75ea8fc91c 100644
--- a/boost/log/utility/manipulators.hpp
+++ b/boost/log/utility/manipulators.hpp
@@ -20,6 +20,7 @@
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/utility/manipulators/to_log.hpp>
#include <boost/log/utility/manipulators/dump.hpp>
+#include <boost/log/utility/manipulators/auto_newline.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
diff --git a/boost/log/utility/manipulators/auto_newline.hpp b/boost/log/utility/manipulators/auto_newline.hpp
new file mode 100644
index 0000000000..933a670de5
--- /dev/null
+++ b/boost/log/utility/manipulators/auto_newline.hpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright Andrey Semashev 2019.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file utility/manipulators/auto_newline.hpp
+ * \author Andrey Semashev
+ * \date 23.06.2019
+ *
+ * The header contains implementation of a stream manipulator for inserting a newline, unless there is already one inserted.
+ */
+
+#ifndef BOOST_LOG_UTILITY_MANIPULATORS_AUTO_NEWLINE_HPP_INCLUDED_
+#define BOOST_LOG_UTILITY_MANIPULATORS_AUTO_NEWLINE_HPP_INCLUDED_
+
+#include <boost/log/detail/config.hpp>
+#include <boost/log/utility/formatting_ostream_fwd.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * Stream manipulator for inserting a newline character, unless the last character
+ * inserted into the stream is already a newline.
+ */
+struct auto_newline_manip {}
+const auto_newline = {};
+
+/*!
+ * Stream output operator for the \c auto_newline manipulator
+ */
+template< typename CharT, typename TraitsT, typename AllocatorT >
+inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, auto_newline_manip)
+{
+ typedef basic_formatting_ostream< CharT, TraitsT, AllocatorT > stream_type;
+ typedef typename stream_type::char_type char_type;
+ typedef typename stream_type::string_type string_type;
+ if (BOOST_LIKELY(strm.good()))
+ {
+ string_type* str = strm.rdbuf()->storage();
+ if (BOOST_LIKELY(!!str))
+ {
+ strm.rdbuf()->pubsync();
+ if (str->empty() || *str->rbegin() != static_cast< char_type >('\n'))
+ strm.rdbuf()->push_back(static_cast< char_type >('\n'));
+ }
+ }
+
+ return strm;
+}
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_UTILITY_MANIPULATORS_AUTO_NEWLINE_HPP_INCLUDED_
diff --git a/boost/log/utility/manipulators/dump.hpp b/boost/log/utility/manipulators/dump.hpp
index 3341376f39..2c55e5c004 100644
--- a/boost/log/utility/manipulators/dump.hpp
+++ b/boost/log/utility/manipulators/dump.hpp
@@ -128,7 +128,7 @@ public:
template< typename CharT, typename TraitsT >
inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, dump_manip const& manip)
{
- if (strm.good())
+ if (BOOST_LIKELY(strm.good()))
aux::dump_data(manip.get_data(), manip.get_size(), strm);
return strm;
@@ -155,7 +155,7 @@ public:
template< typename CharT, typename TraitsT >
inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, bounded_dump_manip const& manip)
{
- if (strm.good())
+ if (BOOST_LIKELY(strm.good()))
{
const std::size_t size = manip.get_size(), max_size = manip.get_max_size();
if (max_size >= size)
diff --git a/boost/log/utility/setup/console.hpp b/boost/log/utility/setup/console.hpp
index 7212c7b74a..08bfd961f0 100644
--- a/boost/log/utility/setup/console.hpp
+++ b/boost/log/utility/setup/console.hpp
@@ -16,10 +16,12 @@
#define BOOST_LOG_UTILITY_SETUP_CONSOLE_HPP_INCLUDED_
#include <iostream>
+#include <boost/type_traits/is_void.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/core/null_deleter.hpp>
#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/parameter_tools.hpp>
#include <boost/log/detail/sink_init_helpers.hpp>
#ifndef BOOST_LOG_NO_THREADS
#include <boost/log/sinks/sync_frontend.hpp>
@@ -29,7 +31,6 @@
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/keywords/format.hpp>
#include <boost/log/keywords/filter.hpp>
-#include <boost/log/keywords/auto_flush.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
@@ -62,10 +63,9 @@ shared_ptr<
shared_ptr< std::basic_ostream< CharT > > pStream(&strm, boost::null_deleter());
typedef sinks::basic_text_ostream_backend< CharT > backend_t;
- shared_ptr< backend_t > pBackend = boost::make_shared< backend_t >();
+ shared_ptr< backend_t > pBackend = boost::make_shared< backend_t >(args);
pBackend->add_stream(pStream);
- pBackend->auto_flush(args[keywords::auto_flush | false]);
typedef BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< backend_t > sink_t;
shared_ptr< sink_t > pSink = boost::make_shared< sink_t >(pBackend);
@@ -112,7 +112,7 @@ inline shared_ptr<
> add_console_log()
{
return aux::add_console_log(
- aux::default_console_stream< CharT >::get(), keywords::auto_flush = false);
+ aux::default_console_stream< CharT >::get(), log::aux::empty_arg_list());
}
@@ -123,7 +123,7 @@ inline shared_ptr<
>
> add_console_log(std::basic_ostream< CharT >& strm)
{
- return aux::add_console_log(strm, keywords::auto_flush = false);
+ return aux::add_console_log(strm, log::aux::empty_arg_list());
}
template< typename CharT, typename ArgT1 >
@@ -156,6 +156,16 @@ inline shared_ptr<
return aux::add_console_log(strm, (arg1, arg2, arg3));
}
+template< typename CharT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4 >
+inline shared_ptr<
+ BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
+ sinks::basic_text_ostream_backend< CharT >
+ >
+> add_console_log(std::basic_ostream< CharT >& strm, ArgT1 const& arg1, ArgT2 const& arg2, ArgT3 const& arg3, ArgT3 const& arg4)
+{
+ return aux::add_console_log(strm, (arg1, arg2, arg3, arg4));
+}
+
#else // BOOST_LOG_DOXYGEN_PASS
/*!
@@ -170,6 +180,8 @@ inline shared_ptr<
* or a formatter lambda expression (either streaming or Boost.Format-like notation).
* \li \c auto_flush A boolean flag that shows whether the sink should automatically flush the stream
* after each written record.
+ * \li \c auto_newline_mode - Specifies automatic trailing newline insertion mode. Must be a value of
+ * the \c auto_newline_mode enum. By default, is <tt>auto_newline_mode::insert_if_missing</tt>.
* \return Pointer to the constructed sink.
*/
template< typename CharT, typename... ArgsT >
diff --git a/boost/log/utility/setup/file.hpp b/boost/log/utility/setup/file.hpp
index b66f06c2cc..03fef7f30b 100644
--- a/boost/log/utility/setup/file.hpp
+++ b/boost/log/utility/setup/file.hpp
@@ -36,6 +36,8 @@
#include <boost/log/sinks/unlocked_frontend.hpp>
#endif
#include <boost/log/sinks/text_file_backend.hpp>
+#include <boost/log/keywords/format.hpp>
+#include <boost/log/keywords/filter.hpp>
#include <boost/log/keywords/scan_method.hpp>
#include <boost/log/detail/header.hpp>
@@ -164,6 +166,8 @@ BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_PARAMETER_ARGS, BOOST_LOG_INIT_LOG_TO_F
* \li \c time_based_rotation The predicate for time-based file rotations. See <tt>basic_text_file_backend</tt>.
* \li \c auto_flush A boolean flag that shows whether the sink should automatically flush the file
* after each written record.
+ * \li \c auto_newline_mode - Specifies automatic trailing newline insertion mode. Must be a value of
+ * the \c auto_newline_mode enum. By default, is <tt>auto_newline_mode::insert_if_missing</tt>.
* \li \c target The target directory to store rotated files in. See <tt>sinks::file::make_collector</tt>.
* \li \c max_size The maximum total size of rotated files in the target directory. See <tt>sinks::file::make_collector</tt>.
* \li \c min_free_space Minimum free space in the target directory. See <tt>sinks::file::make_collector</tt>.
diff --git a/boost/math/cstdfloat/cstdfloat_cmath.hpp b/boost/math/cstdfloat/cstdfloat_cmath.hpp
index 83fb480dc6..ba77b2a7ad 100644
--- a/boost/math/cstdfloat/cstdfloat_cmath.hpp
+++ b/boost/math/cstdfloat/cstdfloat_cmath.hpp
@@ -10,595 +10,1085 @@
// Implement quadruple-precision <cmath> support.
#ifndef _BOOST_CSTDFLOAT_CMATH_2014_02_15_HPP_
- #define _BOOST_CSTDFLOAT_CMATH_2014_02_15_HPP_
-
- #include <boost/math/cstdfloat/cstdfloat_types.hpp>
- #include <boost/math/cstdfloat/cstdfloat_limits.hpp>
-
- #if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
-
- #include <cmath>
- #include <stdexcept>
- #include <boost/cstdint.hpp>
- #include <boost/static_assert.hpp>
- #include <boost/throw_exception.hpp>
-
- #if defined(_WIN32) && defined(__GNUC__)
- // Several versions of Mingw and probably cygwin too have broken
- // libquadmath implementations that segfault as soon as you call
- // expq or any function that depends on it.
- #define BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
- #endif
-
- // Here is a helper function used for raising the value of a given
- // floating-point type to the power of n, where n has integral type.
- namespace boost { namespace math { namespace cstdfloat { namespace detail {
-
- template<class float_type, class integer_type>
- inline float_type pown(const float_type& x, const integer_type p)
- {
- const bool isneg = (x < 0);
- const bool isnan = (x != x);
- const bool isinf = ((!isneg) ? bool(+x > (std::numeric_limits<float_type>::max)())
- : bool(-x > (std::numeric_limits<float_type>::max)()));
-
- if(isnan) { return x; }
-
- if(isinf) { return std::numeric_limits<float_type>::quiet_NaN(); }
-
- const bool x_is_neg = (x < 0);
- const float_type abs_x = (x_is_neg ? -x : x);
-
- if(p < static_cast<integer_type>(0))
- {
- if(abs_x < (std::numeric_limits<float_type>::min)())
- {
- return (x_is_neg ? -std::numeric_limits<float_type>::infinity()
- : +std::numeric_limits<float_type>::infinity());
- }
- else
- {
- return float_type(1) / pown(x, static_cast<integer_type>(-p));
- }
- }
-
- if(p == static_cast<integer_type>(0))
- {
- return float_type(1);
- }
- else
- {
- if(p == static_cast<integer_type>(1)) { return x; }
+#define _BOOST_CSTDFLOAT_CMATH_2014_02_15_HPP_
+
+#include <boost/math/cstdfloat/cstdfloat_types.hpp>
+#include <boost/math/cstdfloat/cstdfloat_limits.hpp>
+
+#if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
+
+#include <cmath>
+#include <stdexcept>
+#include <iostream>
+#include <boost/cstdint.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/scoped_array.hpp>
+
+#if defined(_WIN32) && defined(__GNUC__)
+ // Several versions of Mingw and probably cygwin too have broken
+ // libquadmath implementations that segfault as soon as you call
+ // expq or any function that depends on it.
+#define BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
+#endif
- if(abs_x > (std::numeric_limits<float_type>::max)())
- {
- return (x_is_neg ? -std::numeric_limits<float_type>::infinity()
- : +std::numeric_limits<float_type>::infinity());
+// Here is a helper function used for raising the value of a given
+// floating-point type to the power of n, where n has integral type.
+namespace boost {
+ namespace math {
+ namespace cstdfloat {
+ namespace detail {
+
+ template<class float_type, class integer_type>
+ inline float_type pown(const float_type& x, const integer_type p)
+ {
+ const bool isneg = (x < 0);
+ const bool isnan = (x != x);
+ const bool isinf = ((!isneg) ? bool(+x > (std::numeric_limits<float_type>::max)())
+ : bool(-x > (std::numeric_limits<float_type>::max)()));
+
+ if (isnan) { return x; }
+
+ if (isinf) { return std::numeric_limits<float_type>::quiet_NaN(); }
+
+ const bool x_is_neg = (x < 0);
+ const float_type abs_x = (x_is_neg ? -x : x);
+
+ if (p < static_cast<integer_type>(0))
+ {
+ if (abs_x < (std::numeric_limits<float_type>::min)())
+ {
+ return (x_is_neg ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::infinity());
+ }
+ else
+ {
+ return float_type(1) / pown(x, static_cast<integer_type>(-p));
+ }
+ }
+
+ if (p == static_cast<integer_type>(0))
+ {
+ return float_type(1);
+ }
+ else
+ {
+ if (p == static_cast<integer_type>(1)) { return x; }
+
+ if (abs_x > (std::numeric_limits<float_type>::max)())
+ {
+ return (x_is_neg ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::infinity());
+ }
+
+ if (p == static_cast<integer_type>(2)) { return (x * x); }
+ else if (p == static_cast<integer_type>(3)) { return ((x * x) * x); }
+ else if (p == static_cast<integer_type>(4)) { const float_type x2 = (x * x); return (x2 * x2); }
+ else
+ {
+ // The variable xn stores the binary powers of x.
+ float_type result(((p % integer_type(2)) != integer_type(0)) ? x : float_type(1));
+ float_type xn(x);
+
+ integer_type p2 = p;
+
+ while (integer_type(p2 /= 2) != integer_type(0))
+ {
+ // Square xn for each binary power.
+ xn *= xn;
+
+ const bool has_binary_power = (integer_type(p2 % integer_type(2)) != integer_type(0));
+
+ if (has_binary_power)
+ {
+ // Multiply the result with each binary power contained in the exponent.
+ result *= xn;
+ }
+ }
+
+ return result;
+ }
+ }
+ }
+
+ }
}
+ }
+} // boost::math::cstdfloat::detail
+
+// We will now define preprocessor symbols representing quadruple-precision <cmath> functions.
+#if defined(BOOST_INTEL)
+#define BOOST_CSTDFLOAT_FLOAT128_LDEXP __ldexpq
+#define BOOST_CSTDFLOAT_FLOAT128_FREXP __frexpq
+#define BOOST_CSTDFLOAT_FLOAT128_FABS __fabsq
+#define BOOST_CSTDFLOAT_FLOAT128_FLOOR __floorq
+#define BOOST_CSTDFLOAT_FLOAT128_CEIL __ceilq
+#if !defined(BOOST_CSTDFLOAT_FLOAT128_SQRT)
+#define BOOST_CSTDFLOAT_FLOAT128_SQRT __sqrtq
+#endif
+#define BOOST_CSTDFLOAT_FLOAT128_TRUNC __truncq
+#define BOOST_CSTDFLOAT_FLOAT128_EXP __expq
+#define BOOST_CSTDFLOAT_FLOAT128_EXPM1 __expm1q
+#define BOOST_CSTDFLOAT_FLOAT128_POW __powq
+#define BOOST_CSTDFLOAT_FLOAT128_LOG __logq
+#define BOOST_CSTDFLOAT_FLOAT128_LOG10 __log10q
+#define BOOST_CSTDFLOAT_FLOAT128_SIN __sinq
+#define BOOST_CSTDFLOAT_FLOAT128_COS __cosq
+#define BOOST_CSTDFLOAT_FLOAT128_TAN __tanq
+#define BOOST_CSTDFLOAT_FLOAT128_ASIN __asinq
+#define BOOST_CSTDFLOAT_FLOAT128_ACOS __acosq
+#define BOOST_CSTDFLOAT_FLOAT128_ATAN __atanq
+#define BOOST_CSTDFLOAT_FLOAT128_SINH __sinhq
+#define BOOST_CSTDFLOAT_FLOAT128_COSH __coshq
+#define BOOST_CSTDFLOAT_FLOAT128_TANH __tanhq
+#define BOOST_CSTDFLOAT_FLOAT128_ASINH __asinhq
+#define BOOST_CSTDFLOAT_FLOAT128_ACOSH __acoshq
+#define BOOST_CSTDFLOAT_FLOAT128_ATANH __atanhq
+#define BOOST_CSTDFLOAT_FLOAT128_FMOD __fmodq
+#define BOOST_CSTDFLOAT_FLOAT128_ATAN2 __atan2q
+#define BOOST_CSTDFLOAT_FLOAT128_LGAMMA __lgammaq
+#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA __tgammaq
+// begin more functions
+#define BOOST_CSTDFLOAT_FLOAT128_REMAINDER __remainderq
+#define BOOST_CSTDFLOAT_FLOAT128_REMQUO __remquoq
+#define BOOST_CSTDFLOAT_FLOAT128_FMA __fmaq
+#define BOOST_CSTDFLOAT_FLOAT128_FMAX __fmaxq
+#define BOOST_CSTDFLOAT_FLOAT128_FMIN __fminq
+#define BOOST_CSTDFLOAT_FLOAT128_FDIM __fdimq
+#define BOOST_CSTDFLOAT_FLOAT128_NAN __nanq
+//#define BOOST_CSTDFLOAT_FLOAT128_EXP2 __exp2q
+#define BOOST_CSTDFLOAT_FLOAT128_LOG2 __log2q
+#define BOOST_CSTDFLOAT_FLOAT128_LOG1P __log1pq
+#define BOOST_CSTDFLOAT_FLOAT128_CBRT __cbrtq
+#define BOOST_CSTDFLOAT_FLOAT128_HYPOT __hypotq
+#define BOOST_CSTDFLOAT_FLOAT128_ERF __erfq
+#define BOOST_CSTDFLOAT_FLOAT128_ERFC __erfcq
+#define BOOST_CSTDFLOAT_FLOAT128_LLROUND __llroundq
+#define BOOST_CSTDFLOAT_FLOAT128_LROUND __lroundq
+#define BOOST_CSTDFLOAT_FLOAT128_ROUND __roundq
+#define BOOST_CSTDFLOAT_FLOAT128_NEARBYINT __nearbyintq
+#define BOOST_CSTDFLOAT_FLOAT128_LLRINT __llrintq
+#define BOOST_CSTDFLOAT_FLOAT128_LRINT __lrintq
+#define BOOST_CSTDFLOAT_FLOAT128_RINT __rintq
+#define BOOST_CSTDFLOAT_FLOAT128_MODF __modfq
+#define BOOST_CSTDFLOAT_FLOAT128_SCALBLN __scalblnq
+#define BOOST_CSTDFLOAT_FLOAT128_SCALBN __scalbnq
+#define BOOST_CSTDFLOAT_FLOAT128_ILOGB __ilogbq
+#define BOOST_CSTDFLOAT_FLOAT128_LOGB __logbq
+#define BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER __nextafterq
+//#define BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD __nexttowardq
+#define BOOST_CSTDFLOAT_FLOAT128_COPYSIGN __copysignq
+#define BOOST_CSTDFLOAT_FLOAT128_SIGNBIT __signbitq
+//#define BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY __fpclassifyq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISFINITE __isfiniteq
+#define BOOST_CSTDFLOAT_FLOAT128_ISINF __isinfq
+#define BOOST_CSTDFLOAT_FLOAT128_ISNAN __isnanq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISNORMAL __isnormalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATER __isgreaterq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL __isgreaterequalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESS __islessq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL __islessequalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER __islessgreaterq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED __isunorderedq
+// end more functions
+#elif defined(__GNUC__)
+#define BOOST_CSTDFLOAT_FLOAT128_LDEXP ldexpq
+#define BOOST_CSTDFLOAT_FLOAT128_FREXP frexpq
+#define BOOST_CSTDFLOAT_FLOAT128_FABS fabsq
+#define BOOST_CSTDFLOAT_FLOAT128_FLOOR floorq
+#define BOOST_CSTDFLOAT_FLOAT128_CEIL ceilq
+#if !defined(BOOST_CSTDFLOAT_FLOAT128_SQRT)
+#define BOOST_CSTDFLOAT_FLOAT128_SQRT sqrtq
+#endif
+#define BOOST_CSTDFLOAT_FLOAT128_TRUNC truncq
+#define BOOST_CSTDFLOAT_FLOAT128_POW powq
+#define BOOST_CSTDFLOAT_FLOAT128_LOG logq
+#define BOOST_CSTDFLOAT_FLOAT128_LOG10 log10q
+#define BOOST_CSTDFLOAT_FLOAT128_SIN sinq
+#define BOOST_CSTDFLOAT_FLOAT128_COS cosq
+#define BOOST_CSTDFLOAT_FLOAT128_TAN tanq
+#define BOOST_CSTDFLOAT_FLOAT128_ASIN asinq
+#define BOOST_CSTDFLOAT_FLOAT128_ACOS acosq
+#define BOOST_CSTDFLOAT_FLOAT128_ATAN atanq
+#define BOOST_CSTDFLOAT_FLOAT128_FMOD fmodq
+#define BOOST_CSTDFLOAT_FLOAT128_ATAN2 atan2q
+#define BOOST_CSTDFLOAT_FLOAT128_LGAMMA lgammaq
+#if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS)
+#define BOOST_CSTDFLOAT_FLOAT128_EXP expq
+#define BOOST_CSTDFLOAT_FLOAT128_EXPM1 expm1q
+#define BOOST_CSTDFLOAT_FLOAT128_SINH sinhq
+#define BOOST_CSTDFLOAT_FLOAT128_COSH coshq
+#define BOOST_CSTDFLOAT_FLOAT128_TANH tanhq
+#define BOOST_CSTDFLOAT_FLOAT128_ASINH asinhq
+#define BOOST_CSTDFLOAT_FLOAT128_ACOSH acoshq
+#define BOOST_CSTDFLOAT_FLOAT128_ATANH atanhq
+#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA tgammaq
+#else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
+#define BOOST_CSTDFLOAT_FLOAT128_EXP expq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_SINH sinhq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_COSH coshq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_TANH tanhq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_ASINH asinhq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_ACOSH acoshq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_ATANH atanhq_patch
+#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA tgammaq_patch
+#endif // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
+// begin more functions
+#define BOOST_CSTDFLOAT_FLOAT128_REMAINDER remainderq
+#define BOOST_CSTDFLOAT_FLOAT128_REMQUO remquoq
+#define BOOST_CSTDFLOAT_FLOAT128_FMA fmaq
+#define BOOST_CSTDFLOAT_FLOAT128_FMAX fmaxq
+#define BOOST_CSTDFLOAT_FLOAT128_FMIN fminq
+#define BOOST_CSTDFLOAT_FLOAT128_FDIM fdimq
+#define BOOST_CSTDFLOAT_FLOAT128_NAN nanq
+//#define BOOST_CSTDFLOAT_FLOAT128_EXP2 exp2q
+#define BOOST_CSTDFLOAT_FLOAT128_LOG2 log2q
+#define BOOST_CSTDFLOAT_FLOAT128_LOG1P log1pq
+#define BOOST_CSTDFLOAT_FLOAT128_CBRT cbrtq
+#define BOOST_CSTDFLOAT_FLOAT128_HYPOT hypotq
+#define BOOST_CSTDFLOAT_FLOAT128_ERF erfq
+#define BOOST_CSTDFLOAT_FLOAT128_ERFC erfcq
+#define BOOST_CSTDFLOAT_FLOAT128_LLROUND llroundq
+#define BOOST_CSTDFLOAT_FLOAT128_LROUND lroundq
+#define BOOST_CSTDFLOAT_FLOAT128_ROUND roundq
+#define BOOST_CSTDFLOAT_FLOAT128_NEARBYINT nearbyintq
+#define BOOST_CSTDFLOAT_FLOAT128_LLRINT llrintq
+#define BOOST_CSTDFLOAT_FLOAT128_LRINT lrintq
+#define BOOST_CSTDFLOAT_FLOAT128_RINT rintq
+#define BOOST_CSTDFLOAT_FLOAT128_MODF modfq
+#define BOOST_CSTDFLOAT_FLOAT128_SCALBLN scalblnq
+#define BOOST_CSTDFLOAT_FLOAT128_SCALBN scalbnq
+#define BOOST_CSTDFLOAT_FLOAT128_ILOGB ilogbq
+#define BOOST_CSTDFLOAT_FLOAT128_LOGB logbq
+#define BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER nextafterq
+//#define BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD nexttowardq
+#define BOOST_CSTDFLOAT_FLOAT128_COPYSIGN copysignq
+#define BOOST_CSTDFLOAT_FLOAT128_SIGNBIT signbitq
+//#define BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY fpclassifyq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISFINITE isfiniteq
+#define BOOST_CSTDFLOAT_FLOAT128_ISINF isinfq
+#define BOOST_CSTDFLOAT_FLOAT128_ISNAN isnanq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISNORMAL isnormalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATER isgreaterq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL isgreaterequalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESS islessq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL islessequalq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER islessgreaterq
+//#define BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED isunorderedq
+// end more functions
+#endif
- if (p == static_cast<integer_type>(2)) { return (x * x); }
- else if(p == static_cast<integer_type>(3)) { return ((x * x) * x); }
- else if(p == static_cast<integer_type>(4)) { const float_type x2 = (x * x); return (x2 * x2); }
- else
- {
- // The variable xn stores the binary powers of x.
- float_type result(((p % integer_type(2)) != integer_type(0)) ? x : float_type(1));
- float_type xn (x);
-
- integer_type p2 = p;
-
- while(integer_type(p2 /= 2) != integer_type(0))
- {
- // Square xn for each binary power.
- xn *= xn;
-
- const bool has_binary_power = (integer_type(p2 % integer_type(2)) != integer_type(0));
-
- if(has_binary_power)
- {
- // Multiply the result with each binary power contained in the exponent.
- result *= xn;
- }
- }
-
- return result;
- }
- }
- }
-
- } } } } // boost::math::cstdfloat::detail
-
- // We will now define preprocessor symbols representing quadruple-precision <cmath> functions.
- #if defined(BOOST_INTEL)
- #define BOOST_CSTDFLOAT_FLOAT128_LDEXP __ldexpq
- #define BOOST_CSTDFLOAT_FLOAT128_FREXP __frexpq
- #define BOOST_CSTDFLOAT_FLOAT128_FABS __fabsq
- #define BOOST_CSTDFLOAT_FLOAT128_FLOOR __floorq
- #define BOOST_CSTDFLOAT_FLOAT128_CEIL __ceilq
- #if !defined(BOOST_CSTDFLOAT_FLOAT128_SQRT)
- #define BOOST_CSTDFLOAT_FLOAT128_SQRT __sqrtq
- #endif
- #define BOOST_CSTDFLOAT_FLOAT128_TRUNC __truncq
- #define BOOST_CSTDFLOAT_FLOAT128_EXP __expq
- #define BOOST_CSTDFLOAT_FLOAT128_EXPM1 __expm1q
- #define BOOST_CSTDFLOAT_FLOAT128_POW __powq
- #define BOOST_CSTDFLOAT_FLOAT128_LOG __logq
- #define BOOST_CSTDFLOAT_FLOAT128_LOG10 __log10q
- #define BOOST_CSTDFLOAT_FLOAT128_SIN __sinq
- #define BOOST_CSTDFLOAT_FLOAT128_COS __cosq
- #define BOOST_CSTDFLOAT_FLOAT128_TAN __tanq
- #define BOOST_CSTDFLOAT_FLOAT128_ASIN __asinq
- #define BOOST_CSTDFLOAT_FLOAT128_ACOS __acosq
- #define BOOST_CSTDFLOAT_FLOAT128_ATAN __atanq
- #define BOOST_CSTDFLOAT_FLOAT128_SINH __sinhq
- #define BOOST_CSTDFLOAT_FLOAT128_COSH __coshq
- #define BOOST_CSTDFLOAT_FLOAT128_TANH __tanhq
- #define BOOST_CSTDFLOAT_FLOAT128_ASINH __asinhq
- #define BOOST_CSTDFLOAT_FLOAT128_ACOSH __acoshq
- #define BOOST_CSTDFLOAT_FLOAT128_ATANH __atanhq
- #define BOOST_CSTDFLOAT_FLOAT128_FMOD __fmodq
- #define BOOST_CSTDFLOAT_FLOAT128_ATAN2 __atan2q
- #define BOOST_CSTDFLOAT_FLOAT128_LGAMMA __lgammaq
- #define BOOST_CSTDFLOAT_FLOAT128_TGAMMA __tgammaq
- #elif defined(__GNUC__)
- #define BOOST_CSTDFLOAT_FLOAT128_LDEXP ldexpq
- #define BOOST_CSTDFLOAT_FLOAT128_FREXP frexpq
- #define BOOST_CSTDFLOAT_FLOAT128_FABS fabsq
- #define BOOST_CSTDFLOAT_FLOAT128_FLOOR floorq
- #define BOOST_CSTDFLOAT_FLOAT128_CEIL ceilq
- #if !defined(BOOST_CSTDFLOAT_FLOAT128_SQRT)
- #define BOOST_CSTDFLOAT_FLOAT128_SQRT sqrtq
- #endif
- #define BOOST_CSTDFLOAT_FLOAT128_TRUNC truncq
- #define BOOST_CSTDFLOAT_FLOAT128_POW powq
- #define BOOST_CSTDFLOAT_FLOAT128_LOG logq
- #define BOOST_CSTDFLOAT_FLOAT128_LOG10 log10q
- #define BOOST_CSTDFLOAT_FLOAT128_SIN sinq
- #define BOOST_CSTDFLOAT_FLOAT128_COS cosq
- #define BOOST_CSTDFLOAT_FLOAT128_TAN tanq
- #define BOOST_CSTDFLOAT_FLOAT128_ASIN asinq
- #define BOOST_CSTDFLOAT_FLOAT128_ACOS acosq
- #define BOOST_CSTDFLOAT_FLOAT128_ATAN atanq
- #define BOOST_CSTDFLOAT_FLOAT128_FMOD fmodq
- #define BOOST_CSTDFLOAT_FLOAT128_ATAN2 atan2q
- #define BOOST_CSTDFLOAT_FLOAT128_LGAMMA lgammaq
- #if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS)
- #define BOOST_CSTDFLOAT_FLOAT128_EXP expq
- #define BOOST_CSTDFLOAT_FLOAT128_EXPM1 expm1q_internal
- #define BOOST_CSTDFLOAT_FLOAT128_SINH sinhq
- #define BOOST_CSTDFLOAT_FLOAT128_COSH coshq
- #define BOOST_CSTDFLOAT_FLOAT128_TANH tanhq
- #define BOOST_CSTDFLOAT_FLOAT128_ASINH asinhq
- #define BOOST_CSTDFLOAT_FLOAT128_ACOSH acoshq
- #define BOOST_CSTDFLOAT_FLOAT128_ATANH atanhq
- #define BOOST_CSTDFLOAT_FLOAT128_TGAMMA tgammaq
- #else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
- #define BOOST_CSTDFLOAT_FLOAT128_EXP expq_patch
- #define BOOST_CSTDFLOAT_FLOAT128_SINH sinhq_patch
- #define BOOST_CSTDFLOAT_FLOAT128_COSH coshq_patch
- #define BOOST_CSTDFLOAT_FLOAT128_TANH tanhq_patch
- #define BOOST_CSTDFLOAT_FLOAT128_ASINH asinhq_patch
- #define BOOST_CSTDFLOAT_FLOAT128_ACOSH acoshq_patch
- #define BOOST_CSTDFLOAT_FLOAT128_ATANH atanhq_patch
- #define BOOST_CSTDFLOAT_FLOAT128_TGAMMA tgammaq_patch
- #endif // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
- #endif
-
- // Implement quadruple-precision <cmath> functions in the namespace
- // boost::math::cstdfloat::detail. Subsequently inject these into the
- // std namespace via *using* directive.
-
- // Begin with some forward function declarations. Also implement patches
- // for compilers that have broken float128 exponential functions.
-
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LDEXP (boost::math::cstdfloat::detail::float_internal128_t, int) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FREXP (boost::math::cstdfloat::detail::float_internal128_t, int*) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FABS (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FLOOR (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CEIL (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TRUNC (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_POW (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG10 (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SIN (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COS (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TAN (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASIN (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOS (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN (boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMOD (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN2 (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LGAMMA(boost::math::cstdfloat::detail::float_internal128_t) throw();
-
- #if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS)
-
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP (boost::math::cstdfloat::detail::float_internal128_t x) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
- extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) throw();
-
- #else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
-
- // Forward declaration of the patched exponent function, exp(x).
- inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP (boost::math::cstdfloat::detail::float_internal128_t x);
-
- inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1 (boost::math::cstdfloat::detail::float_internal128_t x)
- {
- // Compute exp(x) - 1 for x small.
-
- // Use an order-36 polynomial approximation of the exponential function
- // in the range of (-ln2 < x < ln2). Scale the argument to this range
- // and subsequently multiply the result by 2^n accordingly.
-
- // Derive the polynomial coefficients with Mathematica(R) by generating
- // a table of high-precision values of exp(x) in the range (-ln2 < x < ln2)
- // and subsequently applying the built-in *Fit* function.
-
- // Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/180}]
- // N[%, 120]
- // Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10, x^11, x^12,
- // x^13, x^14, x^15, x^16, x^17, x^18, x^19, x^20, x^21, x^22,
- // x^23, x^24, x^25, x^26, x^27, x^28, x^29, x^30, x^31, x^32,
- // x^33, x^34, x^35, x^36}, x]
-
- typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
-
- float_type sum;
-
- if(x > BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255))
- {
+// Implement quadruple-precision <cmath> functions in the namespace
+// boost::math::cstdfloat::detail. Subsequently inject these into the
+// std namespace via *using* directive.
+
+// Begin with some forward function declarations. Also implement patches
+// for compilers that have broken float128 exponential functions.
+
+extern "C" int quadmath_snprintf(char*, std::size_t, const char*, ...) throw();
+
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LDEXP(boost::math::cstdfloat::detail::float_internal128_t, int) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FREXP(boost::math::cstdfloat::detail::float_internal128_t, int*) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FABS(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FLOOR(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CEIL(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TRUNC(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_POW(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG10(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SIN(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COS(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TAN(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASIN(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOS(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMOD(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN2(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LGAMMA(boost::math::cstdfloat::detail::float_internal128_t) throw();
+
+// begin more functions
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_REMAINDER(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_REMQUO(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t, int*) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMA(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMAX(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMIN(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FDIM(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NAN(const char*) throw();
+//extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP2 (boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG2(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG1P(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CBRT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_HYPOT(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ERF(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ERFC(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" long long int BOOST_CSTDFLOAT_FLOAT128_LLROUND(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" long int BOOST_CSTDFLOAT_FLOAT128_LROUND(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ROUND(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEARBYINT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" long long int BOOST_CSTDFLOAT_FLOAT128_LLRINT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" long int BOOST_CSTDFLOAT_FLOAT128_LRINT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_RINT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_MODF(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t*) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SCALBLN(boost::math::cstdfloat::detail::float_internal128_t, long int) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SCALBN(boost::math::cstdfloat::detail::float_internal128_t, int) throw();
+extern "C" int BOOST_CSTDFLOAT_FLOAT128_ILOGB(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOGB(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COPYSIGN(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" int BOOST_CSTDFLOAT_FLOAT128_SIGNBIT(boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY (boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISFINITE (boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISINF(boost::math::cstdfloat::detail::float_internal128_t) throw();
+extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISNAN(boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ISNORMAL (boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISGREATER (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISLESS (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER(boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+//extern "C" int BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
+ // end more functions
+
+#if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS)
+
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1(boost::math::cstdfloat::detail::float_internal128_t x) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH(boost::math::cstdfloat::detail::float_internal128_t x) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH(boost::math::cstdfloat::detail::float_internal128_t x) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH(boost::math::cstdfloat::detail::float_internal128_t x) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(boost::math::cstdfloat::detail::float_internal128_t x) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(boost::math::cstdfloat::detail::float_internal128_t x) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(boost::math::cstdfloat::detail::float_internal128_t x) throw();
+extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) throw();
+
+#else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
+
+// Forward declaration of the patched exponent function, exp(x).
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x);
+
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1(boost::math::cstdfloat::detail::float_internal128_t x)
+{
+ // Compute exp(x) - 1 for x small.
+
+ // Use an order-36 polynomial approximation of the exponential function
+ // in the range of (-ln2 < x < ln2). Scale the argument to this range
+ // and subsequently multiply the result by 2^n accordingly.
+
+ // Derive the polynomial coefficients with Mathematica(R) by generating
+ // a table of high-precision values of exp(x) in the range (-ln2 < x < ln2)
+ // and subsequently applying the built-in *Fit* function.
+
+ // Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/180}]
+ // N[%, 120]
+ // Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10, x^11, x^12,
+ // x^13, x^14, x^15, x^16, x^17, x^18, x^19, x^20, x^21, x^22,
+ // x^23, x^24, x^25, x^26, x^27, x^28, x^29, x^30, x^31, x^32,
+ // x^33, x^34, x^35, x^36}, x]
+
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+
+ float_type sum;
+
+ if (x > BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255))
+ {
sum = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x) - float_type(1);
- }
- else
- {
+ }
+ else
+ {
// Compute the polynomial approximation of exp(alpha).
- sum = (((((((((((((((((((((((((((((((((((( float_type(BOOST_FLOAT128_C(2.69291698127774166063293705964720493864630783729857438187365E-42)) * x
- + float_type(BOOST_FLOAT128_C(9.70937085471487654794114679403710456028986572118859594614033E-41))) * x
- + float_type(BOOST_FLOAT128_C(3.38715585158055097155585505318085512156885389014410753080500E-39))) * x
- + float_type(BOOST_FLOAT128_C(1.15162718532861050809222658798662695267019717760563645440433E-37))) * x
- + float_type(BOOST_FLOAT128_C(3.80039074689434663295873584133017767349635602413675471702393E-36))) * x
- + float_type(BOOST_FLOAT128_C(1.21612504934087520075905434734158045947460467096773246215239E-34))) * x
- + float_type(BOOST_FLOAT128_C(3.76998762883139753126119821241037824830069851253295480396224E-33))) * x
- + float_type(BOOST_FLOAT128_C(1.13099628863830344684998293828608215735777107850991029729440E-31))) * x
- + float_type(BOOST_FLOAT128_C(3.27988923706982293204067897468714277771890104022419696770352E-30))) * x
- + float_type(BOOST_FLOAT128_C(9.18368986379558482800593745627556950089950023355628325088207E-29))) * x
- + float_type(BOOST_FLOAT128_C(2.47959626322479746949155352659617642905315302382639380521497E-27))) * x
- + float_type(BOOST_FLOAT128_C(6.44695028438447337900255966737803112935639344283098705091949E-26))) * x
- + float_type(BOOST_FLOAT128_C(1.61173757109611834904452725462599961406036904573072897122957E-24))) * x
- + float_type(BOOST_FLOAT128_C(3.86817017063068403772269360016918092488847584660382953555804E-23))) * x
- + float_type(BOOST_FLOAT128_C(8.89679139245057328674891109315654704307721758924206107351744E-22))) * x
- + float_type(BOOST_FLOAT128_C(1.95729410633912612308475595397946731738088422488032228717097E-20))) * x
- + float_type(BOOST_FLOAT128_C(4.11031762331216485847799061511674191805055663711439605760231E-19))) * x
- + float_type(BOOST_FLOAT128_C(8.22063524662432971695598123977873600603370758794431071426640E-18))) * x
- + float_type(BOOST_FLOAT128_C(1.56192069685862264622163643500633782667263448653185159383285E-16))) * x
- + float_type(BOOST_FLOAT128_C(2.81145725434552076319894558300988749849555291507956994126835E-15))) * x
- + float_type(BOOST_FLOAT128_C(4.77947733238738529743820749111754320727153728139716409114011E-14))) * x
- + float_type(BOOST_FLOAT128_C(7.64716373181981647590113198578807092707697416852226691068627E-13))) * x
- + float_type(BOOST_FLOAT128_C(1.14707455977297247138516979786821056670509688396295740818677E-11))) * x
- + float_type(BOOST_FLOAT128_C(1.60590438368216145993923771701549479323291461578567184216302E-10))) * x
- + float_type(BOOST_FLOAT128_C(2.08767569878680989792100903212014323125428376052986408239620E-09))) * x
- + float_type(BOOST_FLOAT128_C(2.50521083854417187750521083854417187750523408006206780016659E-08))) * x
- + float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573195144226062684604E-07))) * x
- + float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573191310049321957902E-06))) * x
- + float_type(BOOST_FLOAT128_C(0.00002480158730158730158730158730158730158730158730149317774))) * x
- + float_type(BOOST_FLOAT128_C(0.00019841269841269841269841269841269841269841269841293575920))) * x
- + float_type(BOOST_FLOAT128_C(0.00138888888888888888888888888888888888888888888888889071045))) * x
- + float_type(BOOST_FLOAT128_C(0.00833333333333333333333333333333333333333333333333332986595))) * x
- + float_type(BOOST_FLOAT128_C(0.04166666666666666666666666666666666666666666666666666664876))) * x
- + float_type(BOOST_FLOAT128_C(0.16666666666666666666666666666666666666666666666666666669048))) * x
- + float_type(BOOST_FLOAT128_C(0.50000000000000000000000000000000000000000000000000000000006))) * x
- + float_type(BOOST_FLOAT128_C(0.99999999999999999999999999999999999999999999999999999999995))) * x);
- }
-
- return sum;
- }
- inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP (boost::math::cstdfloat::detail::float_internal128_t x)
- {
- // Patch the expq() function for a subset of broken GCC compilers
- // like GCC 4.7, 4.8 on MinGW.
-
- // Use an order-36 polynomial approximation of the exponential function
- // in the range of (-ln2 < x < ln2). Scale the argument to this range
- // and subsequently multiply the result by 2^n accordingly.
-
- // Derive the polynomial coefficients with Mathematica(R) by generating
- // a table of high-precision values of exp(x) in the range (-ln2 < x < ln2)
- // and subsequently applying the built-in *Fit* function.
-
- // Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/180}]
- // N[%, 120]
- // Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10, x^11, x^12,
- // x^13, x^14, x^15, x^16, x^17, x^18, x^19, x^20, x^21, x^22,
- // x^23, x^24, x^25, x^26, x^27, x^28, x^29, x^30, x^31, x^32,
- // x^33, x^34, x^35, x^36}, x]
-
- typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
-
- // Scale the argument x to the range (-ln2 < x < ln2).
- BOOST_CONSTEXPR_OR_CONST float_type one_over_ln2 = float_type(BOOST_FLOAT128_C(1.44269504088896340735992468100189213742664595415299));
- const float_type x_over_ln2 = x * one_over_ln2;
-
- boost::int_fast32_t n;
-
- if(x != x)
- {
+ sum = ((((((((((((((((((((((((((((((((((((float_type(BOOST_FLOAT128_C(2.69291698127774166063293705964720493864630783729857438187365E-42)) * x
+ + float_type(BOOST_FLOAT128_C(9.70937085471487654794114679403710456028986572118859594614033E-41))) * x
+ + float_type(BOOST_FLOAT128_C(3.38715585158055097155585505318085512156885389014410753080500E-39))) * x
+ + float_type(BOOST_FLOAT128_C(1.15162718532861050809222658798662695267019717760563645440433E-37))) * x
+ + float_type(BOOST_FLOAT128_C(3.80039074689434663295873584133017767349635602413675471702393E-36))) * x
+ + float_type(BOOST_FLOAT128_C(1.21612504934087520075905434734158045947460467096773246215239E-34))) * x
+ + float_type(BOOST_FLOAT128_C(3.76998762883139753126119821241037824830069851253295480396224E-33))) * x
+ + float_type(BOOST_FLOAT128_C(1.13099628863830344684998293828608215735777107850991029729440E-31))) * x
+ + float_type(BOOST_FLOAT128_C(3.27988923706982293204067897468714277771890104022419696770352E-30))) * x
+ + float_type(BOOST_FLOAT128_C(9.18368986379558482800593745627556950089950023355628325088207E-29))) * x
+ + float_type(BOOST_FLOAT128_C(2.47959626322479746949155352659617642905315302382639380521497E-27))) * x
+ + float_type(BOOST_FLOAT128_C(6.44695028438447337900255966737803112935639344283098705091949E-26))) * x
+ + float_type(BOOST_FLOAT128_C(1.61173757109611834904452725462599961406036904573072897122957E-24))) * x
+ + float_type(BOOST_FLOAT128_C(3.86817017063068403772269360016918092488847584660382953555804E-23))) * x
+ + float_type(BOOST_FLOAT128_C(8.89679139245057328674891109315654704307721758924206107351744E-22))) * x
+ + float_type(BOOST_FLOAT128_C(1.95729410633912612308475595397946731738088422488032228717097E-20))) * x
+ + float_type(BOOST_FLOAT128_C(4.11031762331216485847799061511674191805055663711439605760231E-19))) * x
+ + float_type(BOOST_FLOAT128_C(8.22063524662432971695598123977873600603370758794431071426640E-18))) * x
+ + float_type(BOOST_FLOAT128_C(1.56192069685862264622163643500633782667263448653185159383285E-16))) * x
+ + float_type(BOOST_FLOAT128_C(2.81145725434552076319894558300988749849555291507956994126835E-15))) * x
+ + float_type(BOOST_FLOAT128_C(4.77947733238738529743820749111754320727153728139716409114011E-14))) * x
+ + float_type(BOOST_FLOAT128_C(7.64716373181981647590113198578807092707697416852226691068627E-13))) * x
+ + float_type(BOOST_FLOAT128_C(1.14707455977297247138516979786821056670509688396295740818677E-11))) * x
+ + float_type(BOOST_FLOAT128_C(1.60590438368216145993923771701549479323291461578567184216302E-10))) * x
+ + float_type(BOOST_FLOAT128_C(2.08767569878680989792100903212014323125428376052986408239620E-09))) * x
+ + float_type(BOOST_FLOAT128_C(2.50521083854417187750521083854417187750523408006206780016659E-08))) * x
+ + float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573195144226062684604E-07))) * x
+ + float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573191310049321957902E-06))) * x
+ + float_type(BOOST_FLOAT128_C(0.00002480158730158730158730158730158730158730158730149317774))) * x
+ + float_type(BOOST_FLOAT128_C(0.00019841269841269841269841269841269841269841269841293575920))) * x
+ + float_type(BOOST_FLOAT128_C(0.00138888888888888888888888888888888888888888888888889071045))) * x
+ + float_type(BOOST_FLOAT128_C(0.00833333333333333333333333333333333333333333333333332986595))) * x
+ + float_type(BOOST_FLOAT128_C(0.04166666666666666666666666666666666666666666666666666664876))) * x
+ + float_type(BOOST_FLOAT128_C(0.16666666666666666666666666666666666666666666666666666669048))) * x
+ + float_type(BOOST_FLOAT128_C(0.50000000000000000000000000000000000000000000000000000000006))) * x
+ + float_type(BOOST_FLOAT128_C(0.99999999999999999999999999999999999999999999999999999999995))) * x);
+ }
+
+ return sum;
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP(boost::math::cstdfloat::detail::float_internal128_t x)
+{
+ // Patch the expq() function for a subset of broken GCC compilers
+ // like GCC 4.7, 4.8 on MinGW.
+
+ // Use an order-36 polynomial approximation of the exponential function
+ // in the range of (-ln2 < x < ln2). Scale the argument to this range
+ // and subsequently multiply the result by 2^n accordingly.
+
+ // Derive the polynomial coefficients with Mathematica(R) by generating
+ // a table of high-precision values of exp(x) in the range (-ln2 < x < ln2)
+ // and subsequently applying the built-in *Fit* function.
+
+ // Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/180}]
+ // N[%, 120]
+ // Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10, x^11, x^12,
+ // x^13, x^14, x^15, x^16, x^17, x^18, x^19, x^20, x^21, x^22,
+ // x^23, x^24, x^25, x^26, x^27, x^28, x^29, x^30, x^31, x^32,
+ // x^33, x^34, x^35, x^36}, x]
+
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+
+ // Scale the argument x to the range (-ln2 < x < ln2).
+ BOOST_CONSTEXPR_OR_CONST float_type one_over_ln2 = float_type(BOOST_FLOAT128_C(1.44269504088896340735992468100189213742664595415299));
+ const float_type x_over_ln2 = x * one_over_ln2;
+
+ boost::int_fast32_t n;
+
+ if (x != x)
+ {
// The argument is NaN.
return std::numeric_limits<float_type>::quiet_NaN();
- }
- else if(::BOOST_CSTDFLOAT_FLOAT128_FABS(x) > BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255))
- {
+ }
+ else if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) > BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255))
+ {
// The absolute value of the argument exceeds ln2.
n = static_cast<boost::int_fast32_t>(::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x_over_ln2));
- }
- else if(::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255))
- {
+ }
+ else if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255))
+ {
// The absolute value of the argument is less than ln2.
n = static_cast<boost::int_fast32_t>(0);
- }
- else
- {
+ }
+ else
+ {
// The absolute value of the argument is exactly equal to ln2 (in the sense of floating-point equality).
return float_type(2);
- }
+ }
- // Check if the argument is very near an integer.
- const float_type floor_of_x = ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x);
+ // Check if the argument is very near an integer.
+ const float_type floor_of_x = ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x);
- if(::BOOST_CSTDFLOAT_FLOAT128_FABS(x - floor_of_x) < float_type(BOOST_CSTDFLOAT_FLOAT128_EPS))
- {
+ if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x - floor_of_x) < float_type(BOOST_CSTDFLOAT_FLOAT128_EPS))
+ {
// Return e^n for arguments very near an integer.
return boost::math::cstdfloat::detail::pown(BOOST_FLOAT128_C(2.71828182845904523536028747135266249775724709369996), static_cast<boost::int_fast32_t>(floor_of_x));
- }
-
- // Compute the scaled argument alpha.
- const float_type alpha = x - (n * BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255));
-
- // Compute the polynomial approximation of expm1(alpha) and add to it
- // in order to obtain the scaled result.
- const float_type scaled_result = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(alpha) + float_type(1);
-
- // Rescale the result and return it.
- return scaled_result * boost::math::cstdfloat::detail::pown(float_type(2), n);
- }
- inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH (boost::math::cstdfloat::detail::float_internal128_t x)
- {
- // Patch the sinhq() function for a subset of broken GCC compilers
- // like GCC 4.7, 4.8 on MinGW.
- typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
-
- // Here, we use the following:
- // Set: ex = exp(x)
- // Set: em1 = expm1(x)
- // Then
- // sinh(x) = (ex - 1/ex) / 2 ; for |x| >= 1
- // sinh(x) = (2em1 + em1^2) / (2ex) ; for |x| < 1
-
- const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
-
- if(::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < float_type(+1))
- {
+ }
+
+ // Compute the scaled argument alpha.
+ const float_type alpha = x - (n * BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255));
+
+ // Compute the polynomial approximation of expm1(alpha) and add to it
+ // in order to obtain the scaled result.
+ const float_type scaled_result = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(alpha) + float_type(1);
+
+ // Rescale the result and return it.
+ return scaled_result * boost::math::cstdfloat::detail::pown(float_type(2), n);
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH(boost::math::cstdfloat::detail::float_internal128_t x)
+{
+ // Patch the sinhq() function for a subset of broken GCC compilers
+ // like GCC 4.7, 4.8 on MinGW.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+
+ // Here, we use the following:
+ // Set: ex = exp(x)
+ // Set: em1 = expm1(x)
+ // Then
+ // sinh(x) = (ex - 1/ex) / 2 ; for |x| >= 1
+ // sinh(x) = (2em1 + em1^2) / (2ex) ; for |x| < 1
+
+ const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
+
+ if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < float_type(+1))
+ {
const float_type em1 = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(x);
return ((em1 * 2) + (em1 * em1)) / (ex * 2);
- }
- else
- {
+ }
+ else
+ {
return (ex - (float_type(1) / ex)) / 2;
- }
- }
- inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH (boost::math::cstdfloat::detail::float_internal128_t x)
- {
- // Patch the coshq() function for a subset of broken GCC compilers
- // like GCC 4.7, 4.8 on MinGW.
- typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
- const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
- return (ex + (float_type(1) / ex)) / 2;
- }
- inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH (boost::math::cstdfloat::detail::float_internal128_t x)
- {
- // Patch the tanhq() function for a subset of broken GCC compilers
- // like GCC 4.7, 4.8 on MinGW.
- typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
- const float_type ex_plus = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
- const float_type ex_minus = (float_type(1) / ex_plus);
- return (ex_plus - ex_minus) / (ex_plus + ex_minus);
- }
- inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(boost::math::cstdfloat::detail::float_internal128_t x) throw()
- {
- // Patch the asinh() function since quadmath does not have it.
- typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
- return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + ::BOOST_CSTDFLOAT_FLOAT128_SQRT((x * x) + float_type(1)));
- }
- inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(boost::math::cstdfloat::detail::float_internal128_t x) throw()
- {
- // Patch the acosh() function since quadmath does not have it.
- typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
- const float_type zp(x + float_type(1));
- const float_type zm(x - float_type(1));
-
- return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + (zp * ::BOOST_CSTDFLOAT_FLOAT128_SQRT(zm / zp)));
- }
- inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(boost::math::cstdfloat::detail::float_internal128_t x) throw()
- {
- // Patch the atanh() function since quadmath does not have it.
- typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
- return ( ::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) + x)
- - ::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) - x)) / 2;
- }
- inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) throw()
- {
- // Patch the tgammaq() function for a subset of broken GCC compilers
- // like GCC 4.7, 4.8 on MinGW.
- typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
-
- if(x > float_type(0))
- {
+ }
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH(boost::math::cstdfloat::detail::float_internal128_t x)
+{
+ // Patch the coshq() function for a subset of broken GCC compilers
+ // like GCC 4.7, 4.8 on MinGW.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+ const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
+ return (ex + (float_type(1) / ex)) / 2;
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH(boost::math::cstdfloat::detail::float_internal128_t x)
+{
+ // Patch the tanhq() function for a subset of broken GCC compilers
+ // like GCC 4.7, 4.8 on MinGW.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+ const float_type ex_plus = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
+ const float_type ex_minus = (float_type(1) / ex_plus);
+ return (ex_plus - ex_minus) / (ex_plus + ex_minus);
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(boost::math::cstdfloat::detail::float_internal128_t x) throw()
+{
+ // Patch the asinh() function since quadmath does not have it.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+ return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + ::BOOST_CSTDFLOAT_FLOAT128_SQRT((x * x) + float_type(1)));
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(boost::math::cstdfloat::detail::float_internal128_t x) throw()
+{
+ // Patch the acosh() function since quadmath does not have it.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+ const float_type zp(x + float_type(1));
+ const float_type zm(x - float_type(1));
+
+ return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + (zp * ::BOOST_CSTDFLOAT_FLOAT128_SQRT(zm / zp)));
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(boost::math::cstdfloat::detail::float_internal128_t x) throw()
+{
+ // Patch the atanh() function since quadmath does not have it.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+ return (::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) + x)
+ - ::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) - x)) / 2;
+}
+inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) throw()
+{
+ // Patch the tgammaq() function for a subset of broken GCC compilers
+ // like GCC 4.7, 4.8 on MinGW.
+ typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
+
+ if (x > float_type(0))
+ {
return ::BOOST_CSTDFLOAT_FLOAT128_EXP(::BOOST_CSTDFLOAT_FLOAT128_LGAMMA(x));
- }
- else if(x < float_type(0))
- {
+ }
+ else if (x < float_type(0))
+ {
// For x < 0, compute tgamma(-x) and use the reflection formula.
- const float_type positive_x = -x;
- float_type gamma_value = ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(positive_x);
- const float_type floor_of_positive_x = ::BOOST_CSTDFLOAT_FLOAT128_FLOOR (positive_x);
+ const float_type positive_x = -x;
+ float_type gamma_value = ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(positive_x);
+ const float_type floor_of_positive_x = ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(positive_x);
// Take the reflection checks (slightly adapted) from <boost/math/gamma.hpp>.
const bool floor_of_z_is_equal_to_z = (positive_x == ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(positive_x));
BOOST_CONSTEXPR_OR_CONST float_type my_pi = BOOST_FLOAT128_C(3.14159265358979323846264338327950288419716939937511);
- if(floor_of_z_is_equal_to_z)
+ if (floor_of_z_is_equal_to_z)
{
- const bool is_odd = ((boost::int32_t(floor_of_positive_x) % boost::int32_t(2)) != boost::int32_t(0));
+ const bool is_odd = ((boost::int32_t(floor_of_positive_x) % boost::int32_t(2)) != boost::int32_t(0));
- return (is_odd ? -std::numeric_limits<float_type>::infinity()
- : +std::numeric_limits<float_type>::infinity());
+ return (is_odd ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::infinity());
}
const float_type sinpx_value = x * ::BOOST_CSTDFLOAT_FLOAT128_SIN(my_pi * x);
gamma_value *= sinpx_value;
- const bool result_is_too_large_to_represent = ( (::BOOST_CSTDFLOAT_FLOAT128_FABS(gamma_value) < float_type(1))
- && (((std::numeric_limits<float_type>::max)() * ::BOOST_CSTDFLOAT_FLOAT128_FABS(gamma_value)) < my_pi));
+ const bool result_is_too_large_to_represent = ((::BOOST_CSTDFLOAT_FLOAT128_FABS(gamma_value) < float_type(1))
+ && (((std::numeric_limits<float_type>::max)() * ::BOOST_CSTDFLOAT_FLOAT128_FABS(gamma_value)) < my_pi));
- if(result_is_too_large_to_represent)
+ if (result_is_too_large_to_represent)
{
- const bool is_odd = ((boost::int32_t(floor_of_positive_x) % boost::int32_t(2)) != boost::int32_t(0));
+ const bool is_odd = ((boost::int32_t(floor_of_positive_x) % boost::int32_t(2)) != boost::int32_t(0));
- return (is_odd ? -std::numeric_limits<float_type>::infinity()
- : +std::numeric_limits<float_type>::infinity());
+ return (is_odd ? -std::numeric_limits<float_type>::infinity()
+ : +std::numeric_limits<float_type>::infinity());
}
gamma_value = -my_pi / gamma_value;
- if((gamma_value > float_type(0)) || (gamma_value < float_type(0)))
+ if ((gamma_value > float_type(0)) || (gamma_value < float_type(0)))
{
- return gamma_value;
+ return gamma_value;
}
else
{
- // The value of gamma is too small to represent. Return 0.0 here.
- return float_type(0);
+ // The value of gamma is too small to represent. Return 0.0 here.
+ return float_type(0);
}
- }
- else
- {
+ }
+ else
+ {
// Gamma of zero is complex infinity. Return NaN here.
return std::numeric_limits<float_type>::quiet_NaN();
- }
- }
- #endif // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
-
- // Define the quadruple-precision <cmath> functions in the namespace boost::math::cstdfloat::detail.
-
- namespace boost { namespace math { namespace cstdfloat { namespace detail {
- inline boost::math::cstdfloat::detail::float_internal128_t ldexp (boost::math::cstdfloat::detail::float_internal128_t x, int n) { return ::BOOST_CSTDFLOAT_FLOAT128_LDEXP (x, n); }
- inline boost::math::cstdfloat::detail::float_internal128_t frexp (boost::math::cstdfloat::detail::float_internal128_t x, int* pn) { return ::BOOST_CSTDFLOAT_FLOAT128_FREXP (x, pn); }
- inline boost::math::cstdfloat::detail::float_internal128_t fabs (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t abs (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t floor (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FLOOR (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t ceil (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CEIL (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t sqrt (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t trunc (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TRUNC (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t exp (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXP (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t pow (boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW (x, a); }
- inline boost::math::cstdfloat::detail::float_internal128_t pow (boost::math::cstdfloat::detail::float_internal128_t x, int a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW (x, boost::math::cstdfloat::detail::float_internal128_t(a)); }
- inline boost::math::cstdfloat::detail::float_internal128_t log (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t log10 (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG10 (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t sin (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIN (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t cos (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COS (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t tan (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TAN (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t asin (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASIN (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t acos (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOS (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t atan (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t sinh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SINH (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t cosh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COSH (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t tanh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TANH (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t asinh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASINH (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t acosh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOSH (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t atanh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATANH (x); }
- inline boost::math::cstdfloat::detail::float_internal128_t fmod (boost::math::cstdfloat::detail::float_internal128_t a, boost::math::cstdfloat::detail::float_internal128_t b) { return ::BOOST_CSTDFLOAT_FLOAT128_FMOD (a, b); }
- inline boost::math::cstdfloat::detail::float_internal128_t atan2 (boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN2 (y, x); }
- inline boost::math::cstdfloat::detail::float_internal128_t lgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LGAMMA(x); }
- inline boost::math::cstdfloat::detail::float_internal128_t tgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(x); }
- } } } } // boost::math::cstdfloat::detail
-
- // We will now inject the quadruple-precision <cmath> functions
- // into the std namespace. This is done via *using* directive.
- namespace std
- {
- using boost::math::cstdfloat::detail::ldexp;
- using boost::math::cstdfloat::detail::frexp;
- using boost::math::cstdfloat::detail::fabs;
+ }
+}
+#endif // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
+
+// Define the quadruple-precision <cmath> functions in the namespace boost::math::cstdfloat::detail.
+
+namespace boost {
+ namespace math {
+ namespace cstdfloat {
+ namespace detail {
+ inline boost::math::cstdfloat::detail::float_internal128_t ldexp(boost::math::cstdfloat::detail::float_internal128_t x, int n) { return ::BOOST_CSTDFLOAT_FLOAT128_LDEXP(x, n); }
+ inline boost::math::cstdfloat::detail::float_internal128_t frexp(boost::math::cstdfloat::detail::float_internal128_t x, int* pn) { return ::BOOST_CSTDFLOAT_FLOAT128_FREXP(x, pn); }
+ inline boost::math::cstdfloat::detail::float_internal128_t fabs(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t abs(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t floor(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t ceil(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CEIL(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t sqrt(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t trunc(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TRUNC(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t exp(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXP(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t expm1(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t pow(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW(x, a); }
+ inline boost::math::cstdfloat::detail::float_internal128_t pow(boost::math::cstdfloat::detail::float_internal128_t x, int a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW(x, boost::math::cstdfloat::detail::float_internal128_t(a)); }
+ inline boost::math::cstdfloat::detail::float_internal128_t log(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t log10(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG10(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t sin(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIN(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t cos(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COS(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t tan(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TAN(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t asin(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASIN(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t acos(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOS(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t atan(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t sinh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SINH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t cosh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COSH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t tanh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TANH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t asinh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASINH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t acosh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOSH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t atanh(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATANH(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t fmod(boost::math::cstdfloat::detail::float_internal128_t a, boost::math::cstdfloat::detail::float_internal128_t b) { return ::BOOST_CSTDFLOAT_FLOAT128_FMOD(a, b); }
+ inline boost::math::cstdfloat::detail::float_internal128_t atan2(boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN2(y, x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t lgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LGAMMA(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t tgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(x); }
+ // begin more functions
+ inline boost::math::cstdfloat::detail::float_internal128_t remainder(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_REMAINDER(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t remquo(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, int* z) { return ::BOOST_CSTDFLOAT_FLOAT128_REMQUO(x, y, z); }
+ inline boost::math::cstdfloat::detail::float_internal128_t fma(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t z) { return BOOST_CSTDFLOAT_FLOAT128_FMA(x, y, z); }
+
+ inline boost::math::cstdfloat::detail::float_internal128_t fmax(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ fmax(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ fmax(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMAX(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t fmin(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ fmin(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ fmin(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FMIN(x, y); }
+
+ inline boost::math::cstdfloat::detail::float_internal128_t fdim(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_FDIM(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t nanq(const char* x) { return ::BOOST_CSTDFLOAT_FLOAT128_NAN(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t exp2(boost::math::cstdfloat::detail::float_internal128_t x)
+ {
+ return ::BOOST_CSTDFLOAT_FLOAT128_POW(boost::math::cstdfloat::detail::float_internal128_t(2), x);
+ }
+ inline boost::math::cstdfloat::detail::float_internal128_t log2(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG2(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t log1p(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG1P(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t cbrt(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CBRT(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t hypot(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t z) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT(x*x + y * y + z * z); }
+ inline boost::math::cstdfloat::detail::float_internal128_t hypot(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ hypot(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ hypot(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_HYPOT(x, y); }
+
+
+ inline boost::math::cstdfloat::detail::float_internal128_t erf(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ERF(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t erfc(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ERFC(x); }
+ inline long long int llround(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LLROUND(x); }
+ inline long int lround(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LROUND(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t round(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ROUND(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t nearbyint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_NEARBYINT(x); }
+ inline long long int llrint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LLRINT(x); }
+ inline long int lrint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LRINT(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t rint(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_RINT(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t modf(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t* y) { return ::BOOST_CSTDFLOAT_FLOAT128_MODF(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t scalbln(boost::math::cstdfloat::detail::float_internal128_t x, long int y) { return ::BOOST_CSTDFLOAT_FLOAT128_SCALBLN(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t scalbn(boost::math::cstdfloat::detail::float_internal128_t x, int y) { return ::BOOST_CSTDFLOAT_FLOAT128_SCALBN(x, y); }
+ inline int ilogb(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ILOGB(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t logb(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOGB(x); }
+ inline boost::math::cstdfloat::detail::float_internal128_t nextafter(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(x, y); }
+ inline boost::math::cstdfloat::detail::float_internal128_t nexttoward(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return -(::BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER(-x, -y)); }
+ inline boost::math::cstdfloat::detail::float_internal128_t copysign BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_COPYSIGN(x, y); }
+ inline bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIGNBIT(x); }
+ inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x)
+ {
+ if (::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x))
+ return FP_NAN;
+ else if (::BOOST_CSTDFLOAT_FLOAT128_ISINF(x))
+ return FP_INFINITE;
+ else if (x == BOOST_FLOAT128_C(0.0))
+ return FP_ZERO;
+
+ if (::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < BOOST_CSTDFLOAT_FLOAT128_MIN)
+ return FP_SUBNORMAL;
+ else
+ return FP_NORMAL;
+ }
+ inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x)
+ {
+ return !::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x) && !::BOOST_CSTDFLOAT_FLOAT128_ISINF(x);
+ }
+ inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ISINF(x); }
+ inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x); }
+ inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x) { return boost::math::cstdfloat::detail::fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(x) == FP_NORMAL; }
+ inline bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y)
+ {
+ if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y))
+ return false;
+ return x > y;
+ }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isgreater BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+ inline bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y)
+ {
+ if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y))
+ return false;
+ return x >= y;
+ }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+ inline bool isless BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y)
+ {
+ if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y))
+ return false;
+ return x < y;
+ }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isless BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isless BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isless BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isless BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+
+ inline bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y)
+ {
+ if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y))
+ return false;
+ return x <= y;
+ }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return islessequal BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+
+ inline bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y)
+ {
+ if (isnan BOOST_PREVENT_MACRO_SUBSTITUTION(x) || isnan BOOST_PREVENT_MACRO_SUBSTITUTION(y))
+ return false;
+ return (x < y) || (x > y);
+ }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+
+ inline bool isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t y) { return ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(x) || ::BOOST_CSTDFLOAT_FLOAT128_ISNAN(y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(boost::math::cstdfloat::detail::float_internal128_t x, T y) { return isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(x, (boost::math::cstdfloat::detail::float_internal128_t)y); }
+ template <class T>
+ inline typename boost::enable_if_c<
+ boost::is_convertible<T, boost::math::cstdfloat::detail::float_internal128_t>::value
+ && !boost::is_same<T, boost::math::cstdfloat::detail::float_internal128_t>::value, boost::math::cstdfloat::detail::float_internal128_t>::type
+ isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(T x, boost::math::cstdfloat::detail::float_internal128_t y) { return isunordered BOOST_PREVENT_MACRO_SUBSTITUTION((boost::math::cstdfloat::detail::float_internal128_t)x, y); }
+
+
+ // end more functions
+ }
+ }
+ }
+} // boost::math::cstdfloat::detail
+
+// We will now inject the quadruple-precision <cmath> functions
+// into the std namespace. This is done via *using* directive.
+namespace std
+{
+ using boost::math::cstdfloat::detail::ldexp;
+ using boost::math::cstdfloat::detail::frexp;
+ using boost::math::cstdfloat::detail::fabs;
#if !(defined(_GLIBCXX_USE_FLOAT128) && defined(__GNUC__) && (__GNUC__ >= 7))
- using boost::math::cstdfloat::detail::abs;
+ using boost::math::cstdfloat::detail::abs;
#endif
- using boost::math::cstdfloat::detail::floor;
- using boost::math::cstdfloat::detail::ceil;
- using boost::math::cstdfloat::detail::sqrt;
- using boost::math::cstdfloat::detail::trunc;
- using boost::math::cstdfloat::detail::exp;
- using boost::math::cstdfloat::detail::pow;
- using boost::math::cstdfloat::detail::log;
- using boost::math::cstdfloat::detail::log10;
- using boost::math::cstdfloat::detail::sin;
- using boost::math::cstdfloat::detail::cos;
- using boost::math::cstdfloat::detail::tan;
- using boost::math::cstdfloat::detail::asin;
- using boost::math::cstdfloat::detail::acos;
- using boost::math::cstdfloat::detail::atan;
- using boost::math::cstdfloat::detail::sinh;
- using boost::math::cstdfloat::detail::cosh;
- using boost::math::cstdfloat::detail::tanh;
- using boost::math::cstdfloat::detail::asinh;
- using boost::math::cstdfloat::detail::acosh;
- using boost::math::cstdfloat::detail::atanh;
- using boost::math::cstdfloat::detail::fmod;
- using boost::math::cstdfloat::detail::atan2;
- using boost::math::cstdfloat::detail::lgamma;
- using boost::math::cstdfloat::detail::tgamma;
- } // namespace std
-
- // We will now remove the preprocessor symbols representing quadruple-precision <cmath>
- // functions from the preprocessor.
-
- #undef BOOST_CSTDFLOAT_FLOAT128_LDEXP
- #undef BOOST_CSTDFLOAT_FLOAT128_FREXP
- #undef BOOST_CSTDFLOAT_FLOAT128_FABS
- #undef BOOST_CSTDFLOAT_FLOAT128_FLOOR
- #undef BOOST_CSTDFLOAT_FLOAT128_CEIL
- #undef BOOST_CSTDFLOAT_FLOAT128_SQRT
- #undef BOOST_CSTDFLOAT_FLOAT128_TRUNC
- #undef BOOST_CSTDFLOAT_FLOAT128_EXP
- #undef BOOST_CSTDFLOAT_FLOAT128_EXPM1
- #undef BOOST_CSTDFLOAT_FLOAT128_POW
- #undef BOOST_CSTDFLOAT_FLOAT128_LOG
- #undef BOOST_CSTDFLOAT_FLOAT128_LOG10
- #undef BOOST_CSTDFLOAT_FLOAT128_SIN
- #undef BOOST_CSTDFLOAT_FLOAT128_COS
- #undef BOOST_CSTDFLOAT_FLOAT128_TAN
- #undef BOOST_CSTDFLOAT_FLOAT128_ASIN
- #undef BOOST_CSTDFLOAT_FLOAT128_ACOS
- #undef BOOST_CSTDFLOAT_FLOAT128_ATAN
- #undef BOOST_CSTDFLOAT_FLOAT128_SINH
- #undef BOOST_CSTDFLOAT_FLOAT128_COSH
- #undef BOOST_CSTDFLOAT_FLOAT128_TANH
- #undef BOOST_CSTDFLOAT_FLOAT128_ASINH
- #undef BOOST_CSTDFLOAT_FLOAT128_ACOSH
- #undef BOOST_CSTDFLOAT_FLOAT128_ATANH
- #undef BOOST_CSTDFLOAT_FLOAT128_FMOD
- #undef BOOST_CSTDFLOAT_FLOAT128_ATAN2
- #undef BOOST_CSTDFLOAT_FLOAT128_LGAMMA
- #undef BOOST_CSTDFLOAT_FLOAT128_TGAMMA
-
- #endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
+ using boost::math::cstdfloat::detail::floor;
+ using boost::math::cstdfloat::detail::ceil;
+ using boost::math::cstdfloat::detail::sqrt;
+ using boost::math::cstdfloat::detail::trunc;
+ using boost::math::cstdfloat::detail::exp;
+ using boost::math::cstdfloat::detail::expm1;
+ using boost::math::cstdfloat::detail::pow;
+ using boost::math::cstdfloat::detail::log;
+ using boost::math::cstdfloat::detail::log10;
+ using boost::math::cstdfloat::detail::sin;
+ using boost::math::cstdfloat::detail::cos;
+ using boost::math::cstdfloat::detail::tan;
+ using boost::math::cstdfloat::detail::asin;
+ using boost::math::cstdfloat::detail::acos;
+ using boost::math::cstdfloat::detail::atan;
+ using boost::math::cstdfloat::detail::sinh;
+ using boost::math::cstdfloat::detail::cosh;
+ using boost::math::cstdfloat::detail::tanh;
+ using boost::math::cstdfloat::detail::asinh;
+ using boost::math::cstdfloat::detail::acosh;
+ using boost::math::cstdfloat::detail::atanh;
+ using boost::math::cstdfloat::detail::fmod;
+ using boost::math::cstdfloat::detail::atan2;
+ using boost::math::cstdfloat::detail::lgamma;
+ using boost::math::cstdfloat::detail::tgamma;
+
+ // begin more functions
+ using boost::math::cstdfloat::detail::remainder;
+ using boost::math::cstdfloat::detail::remquo;
+ using boost::math::cstdfloat::detail::fma;
+ using boost::math::cstdfloat::detail::fmax;
+ using boost::math::cstdfloat::detail::fmin;
+ using boost::math::cstdfloat::detail::fdim;
+ using boost::math::cstdfloat::detail::nanq;
+ using boost::math::cstdfloat::detail::exp2;
+ using boost::math::cstdfloat::detail::log2;
+ using boost::math::cstdfloat::detail::log1p;
+ using boost::math::cstdfloat::detail::cbrt;
+ using boost::math::cstdfloat::detail::hypot;
+ using boost::math::cstdfloat::detail::erf;
+ using boost::math::cstdfloat::detail::erfc;
+ using boost::math::cstdfloat::detail::llround;
+ using boost::math::cstdfloat::detail::lround;
+ using boost::math::cstdfloat::detail::round;
+ using boost::math::cstdfloat::detail::nearbyint;
+ using boost::math::cstdfloat::detail::llrint;
+ using boost::math::cstdfloat::detail::lrint;
+ using boost::math::cstdfloat::detail::rint;
+ using boost::math::cstdfloat::detail::modf;
+ using boost::math::cstdfloat::detail::scalbln;
+ using boost::math::cstdfloat::detail::scalbn;
+ using boost::math::cstdfloat::detail::ilogb;
+ using boost::math::cstdfloat::detail::logb;
+ using boost::math::cstdfloat::detail::nextafter;
+ using boost::math::cstdfloat::detail::nexttoward;
+ using boost::math::cstdfloat::detail::copysign;
+ using boost::math::cstdfloat::detail::signbit;
+ using boost::math::cstdfloat::detail::fpclassify;
+ using boost::math::cstdfloat::detail::isfinite;
+ using boost::math::cstdfloat::detail::isinf;
+ using boost::math::cstdfloat::detail::isnan;
+ using boost::math::cstdfloat::detail::isnormal;
+ using boost::math::cstdfloat::detail::isgreater;
+ using boost::math::cstdfloat::detail::isgreaterequal;
+ using boost::math::cstdfloat::detail::isless;
+ using boost::math::cstdfloat::detail::islessequal;
+ using boost::math::cstdfloat::detail::islessgreater;
+ using boost::math::cstdfloat::detail::isunordered;
+ // end more functions
+
+ //
+ // Very basic iostream operator:
+ //
+ inline std::ostream& operator << (std::ostream& os, __float128 m_value)
+ {
+ std::streamsize digits = os.precision();
+ std::ios_base::fmtflags f = os.flags();
+ std::string s;
+
+ char buf[100];
+ boost::scoped_array<char> buf2;
+ std::string format = "%";
+ if (f & std::ios_base::showpos)
+ format += "+";
+ if (f & std::ios_base::showpoint)
+ format += "#";
+ format += ".*";
+ if (digits == 0)
+ digits = 36;
+ format += "Q";
+ if (f & std::ios_base::scientific)
+ format += "e";
+ else if (f & std::ios_base::fixed)
+ format += "f";
+ else
+ format += "g";
+
+ int v = quadmath_snprintf(buf, 100, format.c_str(), digits, m_value);
+
+ if ((v < 0) || (v >= 99))
+ {
+ int v_max = v;
+ buf2.reset(new char[v + 3]);
+ v = quadmath_snprintf(&buf2[0], v_max + 3, format.c_str(), digits, m_value);
+ if (v >= v_max + 3)
+ {
+ BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of float128_type failed."));
+ }
+ s = &buf2[0];
+ }
+ else
+ s = buf;
+ std::streamsize ss = os.width();
+ if (ss > static_cast<std::streamsize>(s.size()))
+ {
+ char fill = os.fill();
+ if ((os.flags() & std::ios_base::left) == std::ios_base::left)
+ s.append(static_cast<std::string::size_type>(ss - s.size()), fill);
+ else
+ s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - s.size()), fill);
+ }
+
+ return os << s;
+ }
+
+
+} // namespace std
+
+// We will now remove the preprocessor symbols representing quadruple-precision <cmath>
+// functions from the preprocessor.
+
+#undef BOOST_CSTDFLOAT_FLOAT128_LDEXP
+#undef BOOST_CSTDFLOAT_FLOAT128_FREXP
+#undef BOOST_CSTDFLOAT_FLOAT128_FABS
+#undef BOOST_CSTDFLOAT_FLOAT128_FLOOR
+#undef BOOST_CSTDFLOAT_FLOAT128_CEIL
+#undef BOOST_CSTDFLOAT_FLOAT128_SQRT
+#undef BOOST_CSTDFLOAT_FLOAT128_TRUNC
+#undef BOOST_CSTDFLOAT_FLOAT128_EXP
+#undef BOOST_CSTDFLOAT_FLOAT128_EXPM1
+#undef BOOST_CSTDFLOAT_FLOAT128_POW
+#undef BOOST_CSTDFLOAT_FLOAT128_LOG
+#undef BOOST_CSTDFLOAT_FLOAT128_LOG10
+#undef BOOST_CSTDFLOAT_FLOAT128_SIN
+#undef BOOST_CSTDFLOAT_FLOAT128_COS
+#undef BOOST_CSTDFLOAT_FLOAT128_TAN
+#undef BOOST_CSTDFLOAT_FLOAT128_ASIN
+#undef BOOST_CSTDFLOAT_FLOAT128_ACOS
+#undef BOOST_CSTDFLOAT_FLOAT128_ATAN
+#undef BOOST_CSTDFLOAT_FLOAT128_SINH
+#undef BOOST_CSTDFLOAT_FLOAT128_COSH
+#undef BOOST_CSTDFLOAT_FLOAT128_TANH
+#undef BOOST_CSTDFLOAT_FLOAT128_ASINH
+#undef BOOST_CSTDFLOAT_FLOAT128_ACOSH
+#undef BOOST_CSTDFLOAT_FLOAT128_ATANH
+#undef BOOST_CSTDFLOAT_FLOAT128_FMOD
+#undef BOOST_CSTDFLOAT_FLOAT128_ATAN2
+#undef BOOST_CSTDFLOAT_FLOAT128_LGAMMA
+#undef BOOST_CSTDFLOAT_FLOAT128_TGAMMA
+
+// begin more functions
+#undef BOOST_CSTDFLOAT_FLOAT128_REMAINDER
+#undef BOOST_CSTDFLOAT_FLOAT128_REMQUO
+#undef BOOST_CSTDFLOAT_FLOAT128_FMA
+#undef BOOST_CSTDFLOAT_FLOAT128_FMAX
+#undef BOOST_CSTDFLOAT_FLOAT128_FMIN
+#undef BOOST_CSTDFLOAT_FLOAT128_FDIM
+#undef BOOST_CSTDFLOAT_FLOAT128_NAN
+#undef BOOST_CSTDFLOAT_FLOAT128_EXP2
+#undef BOOST_CSTDFLOAT_FLOAT128_LOG2
+#undef BOOST_CSTDFLOAT_FLOAT128_LOG1P
+#undef BOOST_CSTDFLOAT_FLOAT128_CBRT
+#undef BOOST_CSTDFLOAT_FLOAT128_HYPOT
+#undef BOOST_CSTDFLOAT_FLOAT128_ERF
+#undef BOOST_CSTDFLOAT_FLOAT128_ERFC
+#undef BOOST_CSTDFLOAT_FLOAT128_LLROUND
+#undef BOOST_CSTDFLOAT_FLOAT128_LROUND
+#undef BOOST_CSTDFLOAT_FLOAT128_ROUND
+#undef BOOST_CSTDFLOAT_FLOAT128_NEARBYINT
+#undef BOOST_CSTDFLOAT_FLOAT128_LLRINT
+#undef BOOST_CSTDFLOAT_FLOAT128_LRINT
+#undef BOOST_CSTDFLOAT_FLOAT128_RINT
+#undef BOOST_CSTDFLOAT_FLOAT128_MODF
+#undef BOOST_CSTDFLOAT_FLOAT128_SCALBLN
+#undef BOOST_CSTDFLOAT_FLOAT128_SCALBN
+#undef BOOST_CSTDFLOAT_FLOAT128_ILOGB
+#undef BOOST_CSTDFLOAT_FLOAT128_LOGB
+#undef BOOST_CSTDFLOAT_FLOAT128_NEXTAFTER
+#undef BOOST_CSTDFLOAT_FLOAT128_NEXTTOWARD
+#undef BOOST_CSTDFLOAT_FLOAT128_COPYSIGN
+#undef BOOST_CSTDFLOAT_FLOAT128_SIGNBIT
+#undef BOOST_CSTDFLOAT_FLOAT128_FPCLASSIFY
+#undef BOOST_CSTDFLOAT_FLOAT128_ISFINITE
+#undef BOOST_CSTDFLOAT_FLOAT128_ISINF
+#undef BOOST_CSTDFLOAT_FLOAT128_ISNAN
+#undef BOOST_CSTDFLOAT_FLOAT128_ISNORMAL
+#undef BOOST_CSTDFLOAT_FLOAT128_ISGREATER
+#undef BOOST_CSTDFLOAT_FLOAT128_ISGREATEREQUAL
+#undef BOOST_CSTDFLOAT_FLOAT128_ISLESS
+#undef BOOST_CSTDFLOAT_FLOAT128_ISLESSEQUAL
+#undef BOOST_CSTDFLOAT_FLOAT128_ISLESSGREATER
+#undef BOOST_CSTDFLOAT_FLOAT128_ISUNORDERED
+// end more functions
+
+#endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
#endif // _BOOST_CSTDFLOAT_CMATH_2014_02_15_HPP_
+
diff --git a/boost/math/differentiation/autodiff.hpp b/boost/math/differentiation/autodiff.hpp
new file mode 100644
index 0000000000..e98eecab6d
--- /dev/null
+++ b/boost/math/differentiation/autodiff.hpp
@@ -0,0 +1,2053 @@
+// Copyright Matthew Pulver 2018 - 2019.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP
+#define BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP
+
+#include <boost/cstdfloat.hpp>
+#include <boost/math/constants/constants.hpp>
+#include <boost/math/special_functions.hpp>
+#include <boost/math/tools/config.hpp>
+#include <boost/math/tools/promotion.hpp>
+#include <boost/multiprecision/rational_adaptor.hpp>
+
+#include <algorithm>
+#include <array>
+#include <cmath>
+#include <functional>
+#include <limits>
+#include <numeric>
+#include <ostream>
+#include <tuple>
+#include <type_traits>
+
+namespace boost {
+namespace math {
+namespace differentiation {
+// Automatic Differentiation v1
+inline namespace autodiff_v1 {
+namespace detail {
+
+template <typename RealType, typename... RealTypes>
+struct promote_args_n {
+ using type = typename tools::promote_args_2<RealType, typename promote_args_n<RealTypes...>::type>::type;
+};
+
+template <typename RealType>
+struct promote_args_n<RealType> {
+ using type = typename tools::promote_arg<RealType>::type;
+};
+
+} // namespace detail
+
+template <typename RealType, typename... RealTypes>
+using promote = typename detail::promote_args_n<RealType, RealTypes...>::type;
+
+namespace detail {
+
+template <typename RealType, size_t Order>
+class fvar;
+
+template <typename T>
+struct is_fvar_impl : std::false_type {};
+
+template <typename RealType, size_t Order>
+struct is_fvar_impl<fvar<RealType, Order>> : std::true_type {};
+
+template <typename T>
+using is_fvar = is_fvar_impl<decay_t<T>>;
+
+template <typename RealType, size_t Order, size_t... Orders>
+struct nest_fvar {
+ using type = fvar<typename nest_fvar<RealType, Orders...>::type, Order>;
+};
+
+template <typename RealType, size_t Order>
+struct nest_fvar<RealType, Order> {
+ using type = fvar<RealType, Order>;
+};
+
+template <typename>
+struct get_depth_impl : std::integral_constant<size_t, 0> {};
+
+template <typename RealType, size_t Order>
+struct get_depth_impl<fvar<RealType, Order>>
+ : std::integral_constant<size_t, get_depth_impl<RealType>::value + 1> {};
+
+template <typename T>
+using get_depth = get_depth_impl<decay_t<T>>;
+
+template <typename>
+struct get_order_sum_t : std::integral_constant<size_t, 0> {};
+
+template <typename RealType, size_t Order>
+struct get_order_sum_t<fvar<RealType, Order>>
+ : std::integral_constant<size_t, get_order_sum_t<RealType>::value + Order> {};
+
+template <typename T>
+using get_order_sum = get_order_sum_t<decay_t<T>>;
+
+template <typename RealType>
+struct get_root_type {
+ using type = RealType;
+};
+
+template <typename RealType, size_t Order>
+struct get_root_type<fvar<RealType, Order>> {
+ using type = typename get_root_type<RealType>::type;
+};
+
+template <typename RealType, size_t Depth>
+struct type_at {
+ using type = RealType;
+};
+
+template <typename RealType, size_t Order, size_t Depth>
+struct type_at<fvar<RealType, Order>, Depth> {
+ using type = typename conditional<Depth == 0,
+ fvar<RealType, Order>,
+ typename type_at<RealType, Depth - 1>::type>::type;
+};
+
+template <typename RealType, size_t Depth>
+using get_type_at = typename type_at<RealType, Depth>::type;
+
+// Satisfies Boost's Conceptual Requirements for Real Number Types.
+// https://www.boost.org/libs/math/doc/html/math_toolkit/real_concepts.html
+template <typename RealType, size_t Order>
+class fvar {
+ std::array<RealType, Order + 1> v;
+
+ public:
+ using root_type = typename get_root_type<RealType>::type; // RealType in the root fvar<RealType,Order>.
+
+ fvar() = default;
+
+ // Initialize a variable or constant.
+ fvar(root_type const&, bool const is_variable);
+
+ // RealType(cr) | RealType | RealType is copy constructible.
+ fvar(fvar const&) = default;
+
+ // Be aware of implicit casting from one fvar<> type to another by this copy constructor.
+ template <typename RealType2, size_t Order2>
+ fvar(fvar<RealType2, Order2> const&);
+
+ // RealType(ca) | RealType | RealType is copy constructible from the arithmetic types.
+ explicit fvar(root_type const&); // Initialize a constant. (No epsilon terms.)
+
+ template <typename RealType2>
+ fvar(RealType2 const& ca); // Supports any RealType2 for which static_cast<root_type>(ca) compiles.
+
+ // r = cr | RealType& | Assignment operator.
+ fvar& operator=(fvar const&) = default;
+
+ // r = ca | RealType& | Assignment operator from the arithmetic types.
+ // Handled by constructor that takes a single parameter of generic type.
+ // fvar& operator=(root_type const&); // Set a constant.
+
+ // r += cr | RealType& | Adds cr to r.
+ template <typename RealType2, size_t Order2>
+ fvar& operator+=(fvar<RealType2, Order2> const&);
+
+ // r += ca | RealType& | Adds ar to r.
+ fvar& operator+=(root_type const&);
+
+ // r -= cr | RealType& | Subtracts cr from r.
+ template <typename RealType2, size_t Order2>
+ fvar& operator-=(fvar<RealType2, Order2> const&);
+
+ // r -= ca | RealType& | Subtracts ca from r.
+ fvar& operator-=(root_type const&);
+
+ // r *= cr | RealType& | Multiplies r by cr.
+ template <typename RealType2, size_t Order2>
+ fvar& operator*=(fvar<RealType2, Order2> const&);
+
+ // r *= ca | RealType& | Multiplies r by ca.
+ fvar& operator*=(root_type const&);
+
+ // r /= cr | RealType& | Divides r by cr.
+ template <typename RealType2, size_t Order2>
+ fvar& operator/=(fvar<RealType2, Order2> const&);
+
+ // r /= ca | RealType& | Divides r by ca.
+ fvar& operator/=(root_type const&);
+
+ // -r | RealType | Unary Negation.
+ fvar operator-() const;
+
+ // +r | RealType& | Identity Operation.
+ fvar const& operator+() const;
+
+ // cr + cr2 | RealType | Binary Addition
+ template <typename RealType2, size_t Order2>
+ promote<fvar, fvar<RealType2, Order2>> operator+(fvar<RealType2, Order2> const&) const;
+
+ // cr + ca | RealType | Binary Addition
+ fvar operator+(root_type const&) const;
+
+ // ca + cr | RealType | Binary Addition
+ template <typename RealType2, size_t Order2>
+ friend fvar<RealType2, Order2> operator+(typename fvar<RealType2, Order2>::root_type const&,
+ fvar<RealType2, Order2> const&);
+
+ // cr - cr2 | RealType | Binary Subtraction
+ template <typename RealType2, size_t Order2>
+ promote<fvar, fvar<RealType2, Order2>> operator-(fvar<RealType2, Order2> const&) const;
+
+ // cr - ca | RealType | Binary Subtraction
+ fvar operator-(root_type const&) const;
+
+ // ca - cr | RealType | Binary Subtraction
+ template <typename RealType2, size_t Order2>
+ friend fvar<RealType2, Order2> operator-(typename fvar<RealType2, Order2>::root_type const&,
+ fvar<RealType2, Order2> const&);
+
+ // cr * cr2 | RealType | Binary Multiplication
+ template <typename RealType2, size_t Order2>
+ promote<fvar, fvar<RealType2, Order2>> operator*(fvar<RealType2, Order2> const&)const;
+
+ // cr * ca | RealType | Binary Multiplication
+ fvar operator*(root_type const&)const;
+
+ // ca * cr | RealType | Binary Multiplication
+ template <typename RealType2, size_t Order2>
+ friend fvar<RealType2, Order2> operator*(typename fvar<RealType2, Order2>::root_type const&,
+ fvar<RealType2, Order2> const&);
+
+ // cr / cr2 | RealType | Binary Subtraction
+ template <typename RealType2, size_t Order2>
+ promote<fvar, fvar<RealType2, Order2>> operator/(fvar<RealType2, Order2> const&) const;
+
+ // cr / ca | RealType | Binary Subtraction
+ fvar operator/(root_type const&) const;
+
+ // ca / cr | RealType | Binary Subtraction
+ template <typename RealType2, size_t Order2>
+ friend fvar<RealType2, Order2> operator/(typename fvar<RealType2, Order2>::root_type const&,
+ fvar<RealType2, Order2> const&);
+
+ // For all comparison overloads, only the root term is compared.
+
+ // cr == cr2 | bool | Equality Comparison
+ template <typename RealType2, size_t Order2>
+ bool operator==(fvar<RealType2, Order2> const&) const;
+
+ // cr == ca | bool | Equality Comparison
+ bool operator==(root_type const&) const;
+
+ // ca == cr | bool | Equality Comparison
+ template <typename RealType2, size_t Order2>
+ friend bool operator==(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
+
+ // cr != cr2 | bool | Inequality Comparison
+ template <typename RealType2, size_t Order2>
+ bool operator!=(fvar<RealType2, Order2> const&) const;
+
+ // cr != ca | bool | Inequality Comparison
+ bool operator!=(root_type const&) const;
+
+ // ca != cr | bool | Inequality Comparison
+ template <typename RealType2, size_t Order2>
+ friend bool operator!=(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
+
+ // cr <= cr2 | bool | Less than equal to.
+ template <typename RealType2, size_t Order2>
+ bool operator<=(fvar<RealType2, Order2> const&) const;
+
+ // cr <= ca | bool | Less than equal to.
+ bool operator<=(root_type const&) const;
+
+ // ca <= cr | bool | Less than equal to.
+ template <typename RealType2, size_t Order2>
+ friend bool operator<=(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
+
+ // cr >= cr2 | bool | Greater than equal to.
+ template <typename RealType2, size_t Order2>
+ bool operator>=(fvar<RealType2, Order2> const&) const;
+
+ // cr >= ca | bool | Greater than equal to.
+ bool operator>=(root_type const&) const;
+
+ // ca >= cr | bool | Greater than equal to.
+ template <typename RealType2, size_t Order2>
+ friend bool operator>=(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
+
+ // cr < cr2 | bool | Less than comparison.
+ template <typename RealType2, size_t Order2>
+ bool operator<(fvar<RealType2, Order2> const&) const;
+
+ // cr < ca | bool | Less than comparison.
+ bool operator<(root_type const&) const;
+
+ // ca < cr | bool | Less than comparison.
+ template <typename RealType2, size_t Order2>
+ friend bool operator<(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
+
+ // cr > cr2 | bool | Greater than comparison.
+ template <typename RealType2, size_t Order2>
+ bool operator>(fvar<RealType2, Order2> const&) const;
+
+ // cr > ca | bool | Greater than comparison.
+ bool operator>(root_type const&) const;
+
+ // ca > cr | bool | Greater than comparison.
+ template <typename RealType2, size_t Order2>
+ friend bool operator>(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
+
+ // Will throw std::out_of_range if Order < order.
+ template <typename... Orders>
+ get_type_at<RealType, sizeof...(Orders)> at(size_t order, Orders... orders) const;
+
+ template <typename... Orders>
+ get_type_at<fvar, sizeof...(Orders)> derivative(Orders... orders) const;
+
+ const RealType& operator[](size_t) const;
+
+ fvar inverse() const; // Multiplicative inverse.
+
+ fvar& negate(); // Negate and return reference to *this.
+
+ static constexpr size_t depth = get_depth<fvar>::value; // Number of nested std::array<RealType,Order>.
+
+ static constexpr size_t order_sum = get_order_sum<fvar>::value;
+
+ explicit operator root_type() const; // Must be explicit, otherwise overloaded operators are ambiguous.
+
+ template <typename T, typename = typename boost::enable_if<boost::is_arithmetic<decay_t<T>>>::type>
+ explicit operator T() const; // Must be explicit; multiprecision has trouble without the std::enable_if
+
+ fvar& set_root(root_type const&);
+
+ // Apply coefficients using horner method.
+ template <typename Func, typename Fvar, typename... Fvars>
+ promote<fvar<RealType, Order>, Fvar, Fvars...> apply_coefficients(size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const;
+
+ template <typename Func>
+ fvar apply_coefficients(size_t const order, Func const& f) const;
+
+ // Use when function returns derivative(i)/factorial(i) and may have some infinite derivatives.
+ template <typename Func, typename Fvar, typename... Fvars>
+ promote<fvar<RealType, Order>, Fvar, Fvars...> apply_coefficients_nonhorner(size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const;
+
+ template <typename Func>
+ fvar apply_coefficients_nonhorner(size_t const order, Func const& f) const;
+
+ // Apply derivatives using horner method.
+ template <typename Func, typename Fvar, typename... Fvars>
+ promote<fvar<RealType, Order>, Fvar, Fvars...> apply_derivatives(size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const;
+
+ template <typename Func>
+ fvar apply_derivatives(size_t const order, Func const& f) const;
+
+ // Use when function returns derivative(i) and may have some infinite derivatives.
+ template <typename Func, typename Fvar, typename... Fvars>
+ promote<fvar<RealType, Order>, Fvar, Fvars...> apply_derivatives_nonhorner(size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const;
+
+ template <typename Func>
+ fvar apply_derivatives_nonhorner(size_t const order, Func const& f) const;
+
+ private:
+ RealType epsilon_inner_product(size_t z0,
+ size_t isum0,
+ size_t m0,
+ fvar const& cr,
+ size_t z1,
+ size_t isum1,
+ size_t m1,
+ size_t j) const;
+
+ fvar epsilon_multiply(size_t z0, size_t isum0, fvar const& cr, size_t z1, size_t isum1) const;
+
+ fvar epsilon_multiply(size_t z0, size_t isum0, root_type const& ca) const;
+
+ fvar inverse_apply() const;
+
+ fvar& multiply_assign_by_root_type(bool is_root, root_type const&);
+
+ template <typename RealType2, size_t Orders2>
+ friend class fvar;
+
+ template <typename RealType2, size_t Order2>
+ friend std::ostream& operator<<(std::ostream&, fvar<RealType2, Order2> const&);
+
+ // C++11 Compatibility
+#ifdef BOOST_NO_CXX17_IF_CONSTEXPR
+ template <typename RootType>
+ void fvar_cpp11(std::true_type, RootType const& ca, bool const is_variable);
+
+ template <typename RootType>
+ void fvar_cpp11(std::false_type, RootType const& ca, bool const is_variable);
+
+ template <typename... Orders>
+ get_type_at<RealType, sizeof...(Orders)> at_cpp11(std::true_type, size_t order, Orders... orders) const;
+
+ template <typename... Orders>
+ get_type_at<RealType, sizeof...(Orders)> at_cpp11(std::false_type, size_t order, Orders... orders) const;
+
+ template <typename SizeType>
+ fvar epsilon_multiply_cpp11(std::true_type,
+ SizeType z0,
+ size_t isum0,
+ fvar const& cr,
+ size_t z1,
+ size_t isum1) const;
+
+ template <typename SizeType>
+ fvar epsilon_multiply_cpp11(std::false_type,
+ SizeType z0,
+ size_t isum0,
+ fvar const& cr,
+ size_t z1,
+ size_t isum1) const;
+
+ template <typename SizeType>
+ fvar epsilon_multiply_cpp11(std::true_type, SizeType z0, size_t isum0, root_type const& ca) const;
+
+ template <typename SizeType>
+ fvar epsilon_multiply_cpp11(std::false_type, SizeType z0, size_t isum0, root_type const& ca) const;
+
+ template <typename RootType>
+ fvar& multiply_assign_by_root_type_cpp11(std::true_type, bool is_root, RootType const& ca);
+
+ template <typename RootType>
+ fvar& multiply_assign_by_root_type_cpp11(std::false_type, bool is_root, RootType const& ca);
+
+ template <typename RootType>
+ fvar& negate_cpp11(std::true_type, RootType const&);
+
+ template <typename RootType>
+ fvar& negate_cpp11(std::false_type, RootType const&);
+
+ template <typename RootType>
+ fvar& set_root_cpp11(std::true_type, RootType const& root);
+
+ template <typename RootType>
+ fvar& set_root_cpp11(std::false_type, RootType const& root);
+#endif
+};
+
+// C++11 compatibility
+#ifdef BOOST_NO_CXX17_IF_CONSTEXPR
+#define BOOST_AUTODIFF_IF_CONSTEXPR
+#else
+#define BOOST_AUTODIFF_IF_CONSTEXPR constexpr
+#endif
+
+// Standard Library Support Requirements
+
+// fabs(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fabs(fvar<RealType, Order> const&);
+
+// abs(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> abs(fvar<RealType, Order> const&);
+
+// ceil(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> ceil(fvar<RealType, Order> const&);
+
+// floor(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> floor(fvar<RealType, Order> const&);
+
+// exp(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> exp(fvar<RealType, Order> const&);
+
+// pow(cr, ca) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> pow(fvar<RealType, Order> const&, typename fvar<RealType, Order>::root_type const&);
+
+// pow(ca, cr) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> pow(typename fvar<RealType, Order>::root_type const&, fvar<RealType, Order> const&);
+
+// pow(cr1, cr2) | RealType
+template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
+promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> pow(fvar<RealType1, Order1> const&,
+ fvar<RealType2, Order2> const&);
+
+// sqrt(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> sqrt(fvar<RealType, Order> const&);
+
+// log(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> log(fvar<RealType, Order> const&);
+
+// frexp(cr1, &i) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> frexp(fvar<RealType, Order> const&, int*);
+
+// ldexp(cr1, i) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> ldexp(fvar<RealType, Order> const&, int);
+
+// cos(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> cos(fvar<RealType, Order> const&);
+
+// sin(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> sin(fvar<RealType, Order> const&);
+
+// asin(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> asin(fvar<RealType, Order> const&);
+
+// tan(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> tan(fvar<RealType, Order> const&);
+
+// atan(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> atan(fvar<RealType, Order> const&);
+
+// atan2(cr, ca) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> atan2(fvar<RealType, Order> const&, typename fvar<RealType, Order>::root_type const&);
+
+// atan2(ca, cr) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> atan2(typename fvar<RealType, Order>::root_type const&, fvar<RealType, Order> const&);
+
+// atan2(cr1, cr2) | RealType
+template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
+promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> atan2(fvar<RealType1, Order1> const&,
+ fvar<RealType2, Order2> const&);
+
+// fmod(cr1,cr2) | RealType
+template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
+promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> fmod(fvar<RealType1, Order1> const&,
+ fvar<RealType2, Order2> const&);
+
+// round(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> round(fvar<RealType, Order> const&);
+
+// iround(cr1) | int
+template <typename RealType, size_t Order>
+int iround(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+long lround(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+long long llround(fvar<RealType, Order> const&);
+
+// trunc(cr1) | RealType
+template <typename RealType, size_t Order>
+fvar<RealType, Order> trunc(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+long double truncl(fvar<RealType, Order> const&);
+
+// itrunc(cr1) | int
+template <typename RealType, size_t Order>
+int itrunc(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+long long lltrunc(fvar<RealType, Order> const&);
+
+// Additional functions
+template <typename RealType, size_t Order>
+fvar<RealType, Order> acos(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> acosh(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> asinh(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> atanh(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> cosh(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> digamma(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> erf(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> erfc(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> lambert_w0(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> lgamma(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> sinc(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> sinh(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> tanh(fvar<RealType, Order> const&);
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> tgamma(fvar<RealType, Order> const&);
+
+template <size_t>
+struct zero : std::integral_constant<size_t, 0> {};
+
+} // namespace detail
+
+template <typename RealType, size_t Order, size_t... Orders>
+using autodiff_fvar = typename detail::nest_fvar<RealType, Order, Orders...>::type;
+
+template <typename RealType, size_t Order, size_t... Orders>
+autodiff_fvar<RealType, Order, Orders...> make_fvar(RealType const& ca) {
+ return autodiff_fvar<RealType, Order, Orders...>(ca, true);
+}
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+namespace detail {
+
+template <typename RealType, size_t Order, size_t... Is>
+auto make_fvar_for_tuple(std::index_sequence<Is...>, RealType const& ca) {
+ return make_fvar<RealType, zero<Is>::value..., Order>(ca);
+}
+
+template <typename RealType, size_t... Orders, size_t... Is, typename... RealTypes>
+auto make_ftuple_impl(std::index_sequence<Is...>, RealTypes const&... ca) {
+ return std::make_tuple(make_fvar_for_tuple<RealType, Orders>(std::make_index_sequence<Is>{}, ca)...);
+}
+
+} // namespace detail
+
+template <typename RealType, size_t... Orders, typename... RealTypes>
+auto make_ftuple(RealTypes const&... ca) {
+ static_assert(sizeof...(Orders) == sizeof...(RealTypes),
+ "Number of Orders must match number of function parameters.");
+ return detail::make_ftuple_impl<RealType, Orders...>(std::index_sequence_for<RealTypes...>{}, ca...);
+}
+#endif
+
+namespace detail {
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+template <typename RealType, size_t Order>
+fvar<RealType, Order>::fvar(root_type const& ca, bool const is_variable) {
+ if constexpr (is_fvar<RealType>::value) {
+ v.front() = RealType(ca, is_variable);
+ if constexpr (0 < Order)
+ std::fill(v.begin() + 1, v.end(), static_cast<RealType>(0));
+ } else {
+ v.front() = ca;
+ if constexpr (0 < Order)
+ v[1] = static_cast<root_type>(static_cast<int>(is_variable));
+ if constexpr (1 < Order)
+ std::fill(v.begin() + 2, v.end(), static_cast<RealType>(0));
+ }
+}
+#endif
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+fvar<RealType, Order>::fvar(fvar<RealType2, Order2> const& cr) {
+ for (size_t i = 0; i <= (std::min)(Order, Order2); ++i)
+ v[i] = static_cast<RealType>(cr.v[i]);
+ if BOOST_AUTODIFF_IF_CONSTEXPR (Order2 < Order)
+ std::fill(v.begin() + (Order2 + 1), v.end(), static_cast<RealType>(0));
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order>::fvar(root_type const& ca) : v{{static_cast<RealType>(ca)}} {}
+
+// Can cause compiler error if RealType2 cannot be cast to root_type.
+template <typename RealType, size_t Order>
+template <typename RealType2>
+fvar<RealType, Order>::fvar(RealType2 const& ca) : v{{static_cast<RealType>(ca)}} {}
+
+/*
+template<typename RealType, size_t Order>
+fvar<RealType,Order>& fvar<RealType,Order>::operator=(root_type const& ca)
+{
+ v.front() = static_cast<RealType>(ca);
+ if constexpr (0 < Order)
+ std::fill(v.begin()+1, v.end(), static_cast<RealType>(0));
+ return *this;
+}
+*/
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+fvar<RealType, Order>& fvar<RealType, Order>::operator+=(fvar<RealType2, Order2> const& cr) {
+ for (size_t i = 0; i <= (std::min)(Order, Order2); ++i)
+ v[i] += cr.v[i];
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order>& fvar<RealType, Order>::operator+=(root_type const& ca) {
+ v.front() += ca;
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+fvar<RealType, Order>& fvar<RealType, Order>::operator-=(fvar<RealType2, Order2> const& cr) {
+ for (size_t i = 0; i <= Order; ++i)
+ v[i] -= cr.v[i];
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order>& fvar<RealType, Order>::operator-=(root_type const& ca) {
+ v.front() -= ca;
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+fvar<RealType, Order>& fvar<RealType, Order>::operator*=(fvar<RealType2, Order2> const& cr) {
+ using diff_t = typename std::array<RealType, Order + 1>::difference_type;
+ promote<RealType, RealType2> const zero(0);
+ if BOOST_AUTODIFF_IF_CONSTEXPR (Order <= Order2)
+ for (size_t i = 0, j = Order; i <= Order; ++i, --j)
+ v[j] = std::inner_product(v.cbegin(), v.cend() - diff_t(i), cr.v.crbegin() + diff_t(i), zero);
+ else {
+ for (size_t i = 0, j = Order; i <= Order - Order2; ++i, --j)
+ v[j] = std::inner_product(cr.v.cbegin(), cr.v.cend(), v.crbegin() + diff_t(i), zero);
+ for (size_t i = Order - Order2 + 1, j = Order2 - 1; i <= Order; ++i, --j)
+ v[j] = std::inner_product(cr.v.cbegin(), cr.v.cbegin() + diff_t(j + 1), v.crbegin() + diff_t(i), zero);
+ }
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order>& fvar<RealType, Order>::operator*=(root_type const& ca) {
+ return multiply_assign_by_root_type(true, ca);
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+fvar<RealType, Order>& fvar<RealType, Order>::operator/=(fvar<RealType2, Order2> const& cr) {
+ using diff_t = typename std::array<RealType, Order + 1>::difference_type;
+ RealType const zero(0);
+ v.front() /= cr.v.front();
+ if BOOST_AUTODIFF_IF_CONSTEXPR (Order < Order2)
+ for (size_t i = 1, j = Order2 - 1, k = Order; i <= Order; ++i, --j, --k)
+ (v[i] -= std::inner_product(
+ cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), v.crbegin() + diff_t(k), zero)) /= cr.v.front();
+ else if BOOST_AUTODIFF_IF_CONSTEXPR (0 < Order2)
+ for (size_t i = 1, j = Order2 - 1, k = Order; i <= Order; ++i, j && --j, --k)
+ (v[i] -= std::inner_product(
+ cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), v.crbegin() + diff_t(k), zero)) /= cr.v.front();
+ else
+ for (size_t i = 1; i <= Order; ++i)
+ v[i] /= cr.v.front();
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order>& fvar<RealType, Order>::operator/=(root_type const& ca) {
+ std::for_each(v.begin(), v.end(), [&ca](RealType& x) { x /= ca; });
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fvar<RealType, Order>::operator-() const {
+ fvar<RealType, Order> retval(*this);
+ retval.negate();
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> const& fvar<RealType, Order>::operator+() const {
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+promote<fvar<RealType, Order>, fvar<RealType2, Order2>> fvar<RealType, Order>::operator+(
+ fvar<RealType2, Order2> const& cr) const {
+ promote<fvar<RealType, Order>, fvar<RealType2, Order2>> retval;
+ for (size_t i = 0; i <= (std::min)(Order, Order2); ++i)
+ retval.v[i] = v[i] + cr.v[i];
+ if BOOST_AUTODIFF_IF_CONSTEXPR (Order < Order2)
+ for (size_t i = Order + 1; i <= Order2; ++i)
+ retval.v[i] = cr.v[i];
+ else if BOOST_AUTODIFF_IF_CONSTEXPR (Order2 < Order)
+ for (size_t i = Order2 + 1; i <= Order; ++i)
+ retval.v[i] = v[i];
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fvar<RealType, Order>::operator+(root_type const& ca) const {
+ fvar<RealType, Order> retval(*this);
+ retval.v.front() += ca;
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> operator+(typename fvar<RealType, Order>::root_type const& ca,
+ fvar<RealType, Order> const& cr) {
+ return cr + ca;
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+promote<fvar<RealType, Order>, fvar<RealType2, Order2>> fvar<RealType, Order>::operator-(
+ fvar<RealType2, Order2> const& cr) const {
+ promote<fvar<RealType, Order>, fvar<RealType2, Order2>> retval;
+ for (size_t i = 0; i <= (std::min)(Order, Order2); ++i)
+ retval.v[i] = v[i] - cr.v[i];
+ if BOOST_AUTODIFF_IF_CONSTEXPR (Order < Order2)
+ for (auto i = Order + 1; i <= Order2; ++i)
+ retval.v[i] = -cr.v[i];
+ else if BOOST_AUTODIFF_IF_CONSTEXPR (Order2 < Order)
+ for (auto i = Order2 + 1; i <= Order; ++i)
+ retval.v[i] = v[i];
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fvar<RealType, Order>::operator-(root_type const& ca) const {
+ fvar<RealType, Order> retval(*this);
+ retval.v.front() -= ca;
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> operator-(typename fvar<RealType, Order>::root_type const& ca,
+ fvar<RealType, Order> const& cr) {
+ fvar<RealType, Order> mcr = -cr; // Has same address as retval in operator-() due to NRVO.
+ mcr += ca;
+ return mcr; // <-- This allows for NRVO. The following does not. --> return mcr += ca;
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+promote<fvar<RealType, Order>, fvar<RealType2, Order2>> fvar<RealType, Order>::operator*(
+ fvar<RealType2, Order2> const& cr) const {
+ using diff_t = typename std::array<RealType, Order + 1>::difference_type;
+ promote<RealType, RealType2> const zero(0);
+ promote<fvar<RealType, Order>, fvar<RealType2, Order2>> retval;
+ if BOOST_AUTODIFF_IF_CONSTEXPR (Order < Order2)
+ for (size_t i = 0, j = Order, k = Order2; i <= Order2; ++i, j && --j, --k)
+ retval.v[i] = std::inner_product(v.cbegin(), v.cend() - diff_t(j), cr.v.crbegin() + diff_t(k), zero);
+ else
+ for (size_t i = 0, j = Order2, k = Order; i <= Order; ++i, j && --j, --k)
+ retval.v[i] = std::inner_product(cr.v.cbegin(), cr.v.cend() - diff_t(j), v.crbegin() + diff_t(k), zero);
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fvar<RealType, Order>::operator*(root_type const& ca) const {
+ fvar<RealType, Order> retval(*this);
+ retval *= ca;
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> operator*(typename fvar<RealType, Order>::root_type const& ca,
+ fvar<RealType, Order> const& cr) {
+ return cr * ca;
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+promote<fvar<RealType, Order>, fvar<RealType2, Order2>> fvar<RealType, Order>::operator/(
+ fvar<RealType2, Order2> const& cr) const {
+ using diff_t = typename std::array<RealType, Order + 1>::difference_type;
+ promote<RealType, RealType2> const zero(0);
+ promote<fvar<RealType, Order>, fvar<RealType2, Order2>> retval;
+ retval.v.front() = v.front() / cr.v.front();
+ if BOOST_AUTODIFF_IF_CONSTEXPR (Order < Order2) {
+ for (size_t i = 1, j = Order2 - 1; i <= Order; ++i, --j)
+ retval.v[i] =
+ (v[i] - std::inner_product(
+ cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(j + 1), zero)) /
+ cr.v.front();
+ for (size_t i = Order + 1, j = Order2 - Order - 1; i <= Order2; ++i, --j)
+ retval.v[i] =
+ -std::inner_product(
+ cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(j + 1), zero) /
+ cr.v.front();
+ } else if BOOST_AUTODIFF_IF_CONSTEXPR (0 < Order2)
+ for (size_t i = 1, j = Order2 - 1, k = Order; i <= Order; ++i, j && --j, --k)
+ retval.v[i] =
+ (v[i] - std::inner_product(
+ cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(k), zero)) /
+ cr.v.front();
+ else
+ for (size_t i = 1; i <= Order; ++i)
+ retval.v[i] = v[i] / cr.v.front();
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fvar<RealType, Order>::operator/(root_type const& ca) const {
+ fvar<RealType, Order> retval(*this);
+ retval /= ca;
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> operator/(typename fvar<RealType, Order>::root_type const& ca,
+ fvar<RealType, Order> const& cr) {
+ using diff_t = typename std::array<RealType, Order + 1>::difference_type;
+ fvar<RealType, Order> retval;
+ retval.v.front() = ca / cr.v.front();
+ if BOOST_AUTODIFF_IF_CONSTEXPR (0 < Order) {
+ RealType const zero(0);
+ for (size_t i = 1, j = Order - 1; i <= Order; ++i, --j)
+ retval.v[i] =
+ -std::inner_product(
+ cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(j + 1), zero) /
+ cr.v.front();
+ }
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+bool fvar<RealType, Order>::operator==(fvar<RealType2, Order2> const& cr) const {
+ return v.front() == cr.v.front();
+}
+
+template <typename RealType, size_t Order>
+bool fvar<RealType, Order>::operator==(root_type const& ca) const {
+ return v.front() == ca;
+}
+
+template <typename RealType, size_t Order>
+bool operator==(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
+ return ca == cr.v.front();
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+bool fvar<RealType, Order>::operator!=(fvar<RealType2, Order2> const& cr) const {
+ return v.front() != cr.v.front();
+}
+
+template <typename RealType, size_t Order>
+bool fvar<RealType, Order>::operator!=(root_type const& ca) const {
+ return v.front() != ca;
+}
+
+template <typename RealType, size_t Order>
+bool operator!=(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
+ return ca != cr.v.front();
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+bool fvar<RealType, Order>::operator<=(fvar<RealType2, Order2> const& cr) const {
+ return v.front() <= cr.v.front();
+}
+
+template <typename RealType, size_t Order>
+bool fvar<RealType, Order>::operator<=(root_type const& ca) const {
+ return v.front() <= ca;
+}
+
+template <typename RealType, size_t Order>
+bool operator<=(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
+ return ca <= cr.v.front();
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+bool fvar<RealType, Order>::operator>=(fvar<RealType2, Order2> const& cr) const {
+ return v.front() >= cr.v.front();
+}
+
+template <typename RealType, size_t Order>
+bool fvar<RealType, Order>::operator>=(root_type const& ca) const {
+ return v.front() >= ca;
+}
+
+template <typename RealType, size_t Order>
+bool operator>=(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
+ return ca >= cr.v.front();
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+bool fvar<RealType, Order>::operator<(fvar<RealType2, Order2> const& cr) const {
+ return v.front() < cr.v.front();
+}
+
+template <typename RealType, size_t Order>
+bool fvar<RealType, Order>::operator<(root_type const& ca) const {
+ return v.front() < ca;
+}
+
+template <typename RealType, size_t Order>
+bool operator<(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
+ return ca < cr.v.front();
+}
+
+template <typename RealType, size_t Order>
+template <typename RealType2, size_t Order2>
+bool fvar<RealType, Order>::operator>(fvar<RealType2, Order2> const& cr) const {
+ return v.front() > cr.v.front();
+}
+
+template <typename RealType, size_t Order>
+bool fvar<RealType, Order>::operator>(root_type const& ca) const {
+ return v.front() > ca;
+}
+
+template <typename RealType, size_t Order>
+bool operator>(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
+ return ca > cr.v.front();
+}
+
+ /*** Other methods and functions ***/
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+// f : order -> derivative(order)/factorial(order)
+// Use this when you have the polynomial coefficients, rather than just the derivatives. E.g. See atan2().
+template <typename RealType, size_t Order>
+template <typename Func, typename Fvar, typename... Fvars>
+promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_coefficients(
+ size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+ size_t i = (std::min)(order, order_sum);
+ promote<fvar<RealType, Order>, Fvar, Fvars...> accumulator = cr.apply_coefficients(
+ order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward<Fvars>(fvars)...);
+ while (i--)
+ (accumulator *= epsilon) += cr.apply_coefficients(
+ order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward<Fvars>(fvars)...);
+ return accumulator;
+}
+#endif
+
+// f : order -> derivative(order)/factorial(order)
+// Use this when you have the polynomial coefficients, rather than just the derivatives. E.g. See atan().
+template <typename RealType, size_t Order>
+template <typename Func>
+fvar<RealType, Order> fvar<RealType, Order>::apply_coefficients(size_t const order, Func const& f) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+ size_t i = (std::min)(order, order_sum);
+#else // ODR-use of static constexpr
+ size_t i = order < order_sum ? order : order_sum;
+#endif
+ fvar<RealType, Order> accumulator = f(i);
+ while (i--)
+ (accumulator *= epsilon) += f(i);
+ return accumulator;
+}
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+// f : order -> derivative(order)
+template <typename RealType, size_t Order>
+template <typename Func, typename Fvar, typename... Fvars>
+promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_coefficients_nonhorner(
+ size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+ fvar<RealType, Order> epsilon_i = fvar<RealType, Order>(1); // epsilon to the power of i
+ promote<fvar<RealType, Order>, Fvar, Fvars...> accumulator = cr.apply_coefficients_nonhorner(
+ order,
+ [&f](auto... indices) { return f(0, static_cast<std::size_t>(indices)...); },
+ std::forward<Fvars>(fvars)...);
+ size_t const i_max = (std::min)(order, order_sum);
+ for (size_t i = 1; i <= i_max; ++i) {
+ epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0);
+ accumulator += epsilon_i.epsilon_multiply(
+ i,
+ 0,
+ cr.apply_coefficients_nonhorner(
+ order - i,
+ [&f, i](auto... indices) { return f(i, static_cast<std::size_t>(indices)...); },
+ std::forward<Fvars>(fvars)...),
+ 0,
+ 0);
+ }
+ return accumulator;
+}
+#endif
+
+// f : order -> coefficient(order)
+template <typename RealType, size_t Order>
+template <typename Func>
+fvar<RealType, Order> fvar<RealType, Order>::apply_coefficients_nonhorner(size_t const order,
+ Func const& f) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+ fvar<RealType, Order> epsilon_i = fvar<RealType, Order>(1); // epsilon to the power of i
+ fvar<RealType, Order> accumulator = fvar<RealType, Order>(f(0u));
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+ size_t const i_max = (std::min)(order, order_sum);
+#else // ODR-use of static constexpr
+ size_t const i_max = order < order_sum ? order : order_sum;
+#endif
+ for (size_t i = 1; i <= i_max; ++i) {
+ epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0);
+ accumulator += epsilon_i.epsilon_multiply(i, 0, f(i));
+ }
+ return accumulator;
+}
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+// f : order -> derivative(order)
+template <typename RealType, size_t Order>
+template <typename Func, typename Fvar, typename... Fvars>
+promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_derivatives(
+ size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+ size_t i = (std::min)(order, order_sum);
+ promote<fvar<RealType, Order>, Fvar, Fvars...> accumulator =
+ cr.apply_derivatives(
+ order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward<Fvars>(fvars)...) /
+ factorial<root_type>(static_cast<unsigned>(i));
+ while (i--)
+ (accumulator *= epsilon) +=
+ cr.apply_derivatives(
+ order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward<Fvars>(fvars)...) /
+ factorial<root_type>(static_cast<unsigned>(i));
+ return accumulator;
+}
+#endif
+
+// f : order -> derivative(order)
+template <typename RealType, size_t Order>
+template <typename Func>
+fvar<RealType, Order> fvar<RealType, Order>::apply_derivatives(size_t const order, Func const& f) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+ size_t i = (std::min)(order, order_sum);
+#else // ODR-use of static constexpr
+ size_t i = order < order_sum ? order : order_sum;
+#endif
+ fvar<RealType, Order> accumulator = f(i) / factorial<root_type>(static_cast<unsigned>(i));
+ while (i--)
+ (accumulator *= epsilon) += f(i) / factorial<root_type>(static_cast<unsigned>(i));
+ return accumulator;
+}
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+// f : order -> derivative(order)
+template <typename RealType, size_t Order>
+template <typename Func, typename Fvar, typename... Fvars>
+promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_derivatives_nonhorner(
+ size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+ fvar<RealType, Order> epsilon_i = fvar<RealType, Order>(1); // epsilon to the power of i
+ promote<fvar<RealType, Order>, Fvar, Fvars...> accumulator = cr.apply_derivatives_nonhorner(
+ order,
+ [&f](auto... indices) { return f(0, static_cast<std::size_t>(indices)...); },
+ std::forward<Fvars>(fvars)...);
+ size_t const i_max = (std::min)(order, order_sum);
+ for (size_t i = 1; i <= i_max; ++i) {
+ epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0);
+ accumulator += epsilon_i.epsilon_multiply(
+ i,
+ 0,
+ cr.apply_derivatives_nonhorner(
+ order - i,
+ [&f, i](auto... indices) { return f(i, static_cast<std::size_t>(indices)...); },
+ std::forward<Fvars>(fvars)...) /
+ factorial<root_type>(static_cast<unsigned>(i)),
+ 0,
+ 0);
+ }
+ return accumulator;
+}
+#endif
+
+// f : order -> derivative(order)
+template <typename RealType, size_t Order>
+template <typename Func>
+fvar<RealType, Order> fvar<RealType, Order>::apply_derivatives_nonhorner(size_t const order,
+ Func const& f) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+ fvar<RealType, Order> epsilon_i = fvar<RealType, Order>(1); // epsilon to the power of i
+ fvar<RealType, Order> accumulator = fvar<RealType, Order>(f(0u));
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+ size_t const i_max = (std::min)(order, order_sum);
+#else // ODR-use of static constexpr
+ size_t const i_max = order < order_sum ? order : order_sum;
+#endif
+ for (size_t i = 1; i <= i_max; ++i) {
+ epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0);
+ accumulator += epsilon_i.epsilon_multiply(i, 0, f(i) / factorial<root_type>(static_cast<unsigned>(i)));
+ }
+ return accumulator;
+}
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+// Can throw "std::out_of_range: array::at: __n (which is 7) >= _Nm (which is 7)"
+template <typename RealType, size_t Order>
+template <typename... Orders>
+get_type_at<RealType, sizeof...(Orders)> fvar<RealType, Order>::at(size_t order, Orders... orders) const {
+ if constexpr (0 < sizeof...(Orders))
+ return v.at(order).at(static_cast<std::size_t>(orders)...);
+ else
+ return v.at(order);
+}
+#endif
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+// Can throw "std::out_of_range: array::at: __n (which is 7) >= _Nm (which is 7)"
+template <typename RealType, size_t Order>
+template <typename... Orders>
+get_type_at<fvar<RealType, Order>, sizeof...(Orders)> fvar<RealType, Order>::derivative(
+ Orders... orders) const {
+ static_assert(sizeof...(Orders) <= depth,
+ "Number of parameters to derivative(...) cannot exceed fvar::depth.");
+ return at(static_cast<std::size_t>(orders)...) *
+ (... * factorial<root_type>(static_cast<unsigned>(orders)));
+}
+#endif
+
+template <typename RealType, size_t Order>
+const RealType& fvar<RealType, Order>::operator[](size_t i) const {
+ return v[i];
+}
+
+template <typename RealType, size_t Order>
+RealType fvar<RealType, Order>::epsilon_inner_product(size_t z0,
+ size_t const isum0,
+ size_t const m0,
+ fvar<RealType, Order> const& cr,
+ size_t z1,
+ size_t const isum1,
+ size_t const m1,
+ size_t const j) const {
+ static_assert(is_fvar<RealType>::value, "epsilon_inner_product() must have 1 < depth.");
+ RealType accumulator = RealType();
+ auto const i0_max = m1 < j ? j - m1 : 0;
+ for (auto i0 = m0, i1 = j - m0; i0 <= i0_max; ++i0, --i1)
+ accumulator += v[i0].epsilon_multiply(z0, isum0 + i0, cr.v[i1], z1, isum1 + i1);
+ return accumulator;
+}
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fvar<RealType, Order>::epsilon_multiply(size_t z0,
+ size_t isum0,
+ fvar<RealType, Order> const& cr,
+ size_t z1,
+ size_t isum1) const {
+ using diff_t = typename std::array<RealType, Order + 1>::difference_type;
+ RealType const zero(0);
+ size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0;
+ size_t const m1 = order_sum + isum1 < Order + z1 ? Order + z1 - (order_sum + isum1) : 0;
+ size_t const i_max = m0 + m1 < Order ? Order - (m0 + m1) : 0;
+ fvar<RealType, Order> retval = fvar<RealType, Order>();
+ if constexpr (is_fvar<RealType>::value)
+ for (size_t i = 0, j = Order; i <= i_max; ++i, --j)
+ retval.v[j] = epsilon_inner_product(z0, isum0, m0, cr, z1, isum1, m1, j);
+ else
+ for (size_t i = 0, j = Order; i <= i_max; ++i, --j)
+ retval.v[j] = std::inner_product(
+ v.cbegin() + diff_t(m0), v.cend() - diff_t(i + m1), cr.v.crbegin() + diff_t(i + m0), zero);
+ return retval;
+}
+#endif
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+// When called from outside this method, z0 should be non-zero. Otherwise if z0=0 then it will give an
+// incorrect result of 0 when the root value is 0 and ca=inf, when instead the correct product is nan.
+// If z0=0 then use the regular multiply operator*() instead.
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fvar<RealType, Order>::epsilon_multiply(size_t z0,
+ size_t isum0,
+ root_type const& ca) const {
+ fvar<RealType, Order> retval(*this);
+ size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0;
+ if constexpr (is_fvar<RealType>::value)
+ for (size_t i = m0; i <= Order; ++i)
+ retval.v[i] = retval.v[i].epsilon_multiply(z0, isum0 + i, ca);
+ else
+ for (size_t i = m0; i <= Order; ++i)
+ if (retval.v[i] != static_cast<RealType>(0))
+ retval.v[i] *= ca;
+ return retval;
+}
+#endif
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fvar<RealType, Order>::inverse() const {
+ return static_cast<root_type>(*this) == 0 ? inverse_apply() : 1 / *this;
+}
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+template <typename RealType, size_t Order>
+fvar<RealType, Order>& fvar<RealType, Order>::negate() {
+ if constexpr (is_fvar<RealType>::value)
+ std::for_each(v.begin(), v.end(), [](RealType& r) { r.negate(); });
+ else
+ std::for_each(v.begin(), v.end(), [](RealType& a) { a = -a; });
+ return *this;
+}
+#endif
+
+// This gives log(0.0) = depth(1)(-inf,inf,-inf,inf,-inf,inf)
+// 1 / *this: log(0.0) = depth(1)(-inf,inf,-inf,-nan,-nan,-nan)
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fvar<RealType, Order>::inverse_apply() const {
+ root_type derivatives[order_sum + 1]; // LCOV_EXCL_LINE This causes a false negative on lcov coverage test.
+ root_type const x0 = static_cast<root_type>(*this);
+ *derivatives = 1 / x0;
+ for (size_t i = 1; i <= order_sum; ++i)
+ derivatives[i] = -derivatives[i - 1] * i / x0;
+ return apply_derivatives_nonhorner(order_sum, [&derivatives](size_t j) { return derivatives[j]; });
+}
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+template <typename RealType, size_t Order>
+fvar<RealType, Order>& fvar<RealType, Order>::multiply_assign_by_root_type(bool is_root,
+ root_type const& ca) {
+ auto itr = v.begin();
+ if constexpr (is_fvar<RealType>::value) {
+ itr->multiply_assign_by_root_type(is_root, ca);
+ for (++itr; itr != v.end(); ++itr)
+ itr->multiply_assign_by_root_type(false, ca);
+ } else {
+ if (is_root || *itr != 0)
+ *itr *= ca; // Skip multiplication of 0 by ca=inf to avoid nan, except when is_root.
+ for (++itr; itr != v.end(); ++itr)
+ if (*itr != 0)
+ *itr *= ca;
+ }
+ return *this;
+}
+#endif
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order>::operator root_type() const {
+ return static_cast<root_type>(v.front());
+}
+
+template <typename RealType, size_t Order>
+template <typename T, typename>
+fvar<RealType, Order>::operator T() const {
+ return static_cast<T>(static_cast<root_type>(v.front()));
+}
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+template <typename RealType, size_t Order>
+fvar<RealType, Order>& fvar<RealType, Order>::set_root(root_type const& root) {
+ if constexpr (is_fvar<RealType>::value)
+ v.front().set_root(root);
+ else
+ v.front() = root;
+ return *this;
+}
+#endif
+
+// Standard Library Support Requirements
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fabs(fvar<RealType, Order> const& cr) {
+ typename fvar<RealType, Order>::root_type const zero(0);
+ return cr < zero ? -cr
+ : cr == zero ? fvar<RealType, Order>() // Canonical fabs'(0) = 0.
+ : cr; // Propagate NaN.
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> abs(fvar<RealType, Order> const& cr) {
+ return fabs(cr);
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> ceil(fvar<RealType, Order> const& cr) {
+ using std::ceil;
+ return fvar<RealType, Order>(ceil(static_cast<typename fvar<RealType, Order>::root_type>(cr)));
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> floor(fvar<RealType, Order> const& cr) {
+ using std::floor;
+ return fvar<RealType, Order>(floor(static_cast<typename fvar<RealType, Order>::root_type>(cr)));
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> exp(fvar<RealType, Order> const& cr) {
+ using std::exp;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ root_type const d0 = exp(static_cast<root_type>(cr));
+ return cr.apply_derivatives(order, [&d0](size_t) { return d0; });
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> pow(fvar<RealType, Order> const& x,
+ typename fvar<RealType, Order>::root_type const& y) {
+ using std::pow;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const x0 = static_cast<root_type>(x);
+ root_type derivatives[order + 1]{pow(x0, y)};
+ for (size_t i = 0; i < order && y - i != 0; ++i)
+ derivatives[i + 1] = (y - i) * derivatives[i] / x0;
+ return x.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i]; });
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> pow(typename fvar<RealType, Order>::root_type const& x,
+ fvar<RealType, Order> const& y) {
+ BOOST_MATH_STD_USING
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const y0 = static_cast<root_type>(y);
+ root_type derivatives[order + 1];
+ *derivatives = pow(x, y0);
+ root_type const logx = log(x);
+ for (size_t i = 0; i < order; ++i)
+ derivatives[i + 1] = derivatives[i] * logx;
+ return y.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i]; });
+}
+
+template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
+promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> pow(fvar<RealType1, Order1> const& x,
+ fvar<RealType2, Order2> const& y) {
+ BOOST_MATH_STD_USING
+ using return_type = promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>>;
+ using root_type = typename return_type::root_type;
+ constexpr size_t order = return_type::order_sum;
+ root_type const x0 = static_cast<root_type>(x);
+ root_type const y0 = static_cast<root_type>(y);
+ root_type dxydx[order + 1]{pow(x0, y0)};
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return return_type(*dxydx);
+ else {
+ for (size_t i = 0; i < order && y0 - i != 0; ++i)
+ dxydx[i + 1] = (y0 - i) * dxydx[i] / x0;
+ std::array<fvar<root_type, order>, order + 1> lognx;
+ lognx.front() = fvar<root_type, order>(1);
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+ lognx[1] = log(make_fvar<root_type, order>(x0));
+#else // for compilers that compile this branch when order=0.
+ lognx[(std::min)(size_t(1), order)] = log(make_fvar<root_type, order>(x0));
+#endif
+ for (size_t i = 1; i < order; ++i)
+ lognx[i + 1] = lognx[i] * lognx[1];
+ auto const f = [&dxydx, &lognx](size_t i, size_t j) {
+ size_t binomial = 1;
+ root_type sum = dxydx[i] * static_cast<root_type>(lognx[j]);
+ for (size_t k = 1; k <= i; ++k) {
+ (binomial *= (i - k + 1)) /= k; // binomial_coefficient(i,k)
+ sum += binomial * dxydx[i - k] * lognx[j].derivative(k);
+ }
+ return sum;
+ };
+ if (fabs(x0) < std::numeric_limits<root_type>::epsilon())
+ return x.apply_derivatives_nonhorner(order, f, y);
+ return x.apply_derivatives(order, f, y);
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> sqrt(fvar<RealType, Order> const& cr) {
+ using std::sqrt;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type derivatives[order + 1];
+ root_type const x = static_cast<root_type>(cr);
+ *derivatives = sqrt(x);
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(*derivatives);
+ else {
+ root_type numerator = 0.5;
+ root_type powers = 1;
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+ derivatives[1] = numerator / *derivatives;
+#else // for compilers that compile this branch when order=0.
+ derivatives[(std::min)(size_t(1), order)] = numerator / *derivatives;
+#endif
+ using diff_t = typename std::array<RealType, Order + 1>::difference_type;
+ for (size_t i = 2; i <= order; ++i) {
+ numerator *= static_cast<root_type>(-0.5) * ((static_cast<diff_t>(i) << 1) - 3);
+ powers *= x;
+ derivatives[i] = numerator / (powers * *derivatives);
+ }
+ auto const f = [&derivatives](size_t i) { return derivatives[i]; };
+ if (cr < std::numeric_limits<root_type>::epsilon())
+ return cr.apply_derivatives_nonhorner(order, f);
+ return cr.apply_derivatives(order, f);
+ }
+}
+
+// Natural logarithm. If cr==0 then derivative(i) may have nans due to nans from inverse().
+template <typename RealType, size_t Order>
+fvar<RealType, Order> log(fvar<RealType, Order> const& cr) {
+ using std::log;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = log(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto const d1 = make_fvar<root_type, order - 1>(static_cast<root_type>(cr)).inverse(); // log'(x) = 1 / x
+ return cr.apply_coefficients_nonhorner(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> frexp(fvar<RealType, Order> const& cr, int* exp) {
+ using multiprecision::exp2;
+ using std::exp2;
+ using std::frexp;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ frexp(static_cast<root_type>(cr), exp);
+ return cr * static_cast<root_type>(exp2(-*exp));
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> ldexp(fvar<RealType, Order> const& cr, int exp) {
+ // argument to std::exp2 must be casted to root_type, otherwise std::exp2 returns double (always)
+ using multiprecision::exp2;
+ using std::exp2;
+ return cr * exp2(static_cast<typename fvar<RealType, Order>::root_type>(exp));
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> cos(fvar<RealType, Order> const& cr) {
+ BOOST_MATH_STD_USING
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = cos(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ root_type const d1 = -sin(static_cast<root_type>(cr));
+ root_type const derivatives[4]{d0, d1, -d0, -d1};
+ return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 3]; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> sin(fvar<RealType, Order> const& cr) {
+ BOOST_MATH_STD_USING
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = sin(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ root_type const d1 = cos(static_cast<root_type>(cr));
+ root_type const derivatives[4]{d0, d1, -d0, -d1};
+ return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 3]; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> asin(fvar<RealType, Order> const& cr) {
+ using std::asin;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = asin(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto x = make_fvar<root_type, order - 1>(static_cast<root_type>(cr));
+ auto const d1 = sqrt((x *= x).negate() += 1).inverse(); // asin'(x) = 1 / sqrt(1-x*x).
+ return cr.apply_coefficients_nonhorner(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> tan(fvar<RealType, Order> const& cr) {
+ using std::tan;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = tan(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto c = cos(make_fvar<root_type, order - 1>(static_cast<root_type>(cr)));
+ auto const d1 = (c *= c).inverse(); // tan'(x) = 1 / cos(x)^2
+ return cr.apply_coefficients_nonhorner(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> atan(fvar<RealType, Order> const& cr) {
+ using std::atan;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = atan(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto x = make_fvar<root_type, order - 1>(static_cast<root_type>(cr));
+ auto const d1 = ((x *= x) += 1).inverse(); // atan'(x) = 1 / (x*x+1).
+ return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> atan2(fvar<RealType, Order> const& cr,
+ typename fvar<RealType, Order>::root_type const& ca) {
+ using std::atan2;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = atan2(static_cast<root_type>(cr), ca);
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto y = make_fvar<root_type, order - 1>(static_cast<root_type>(cr));
+ auto const d1 = ca / ((y *= y) += (ca * ca)); // (d/dy)atan2(y,x) = x / (y*y+x*x)
+ return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> atan2(typename fvar<RealType, Order>::root_type const& ca,
+ fvar<RealType, Order> const& cr) {
+ using std::atan2;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = atan2(ca, static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto x = make_fvar<root_type, order - 1>(static_cast<root_type>(cr));
+ auto const d1 = -ca / ((x *= x) += (ca * ca)); // (d/dx)atan2(y,x) = -y / (x*x+y*y)
+ return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
+promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> atan2(fvar<RealType1, Order1> const& cr1,
+ fvar<RealType2, Order2> const& cr2) {
+ using std::atan2;
+ using return_type = promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>>;
+ using root_type = typename return_type::root_type;
+ constexpr size_t order = return_type::order_sum;
+ root_type const y = static_cast<root_type>(cr1);
+ root_type const x = static_cast<root_type>(cr2);
+ root_type const d00 = atan2(y, x);
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return return_type(d00);
+ else {
+ constexpr size_t order1 = fvar<RealType1, Order1>::order_sum;
+ constexpr size_t order2 = fvar<RealType2, Order2>::order_sum;
+ auto x01 = make_fvar<typename fvar<RealType2, Order2>::root_type, order2 - 1>(x);
+ auto const d01 = -y / ((x01 *= x01) += (y * y));
+ auto y10 = make_fvar<typename fvar<RealType1, Order1>::root_type, order1 - 1>(y);
+ auto x10 = make_fvar<typename fvar<RealType2, Order2>::root_type, 0, order2>(x);
+ auto const d10 = x10 / ((x10 * x10) + (y10 *= y10));
+ auto const f = [&d00, &d01, &d10](size_t i, size_t j) {
+ return i ? d10[i - 1][j] / i : j ? d01[j - 1] / j : d00;
+ };
+ return cr1.apply_coefficients(order, f, cr2);
+ }
+}
+
+template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
+promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> fmod(fvar<RealType1, Order1> const& cr1,
+ fvar<RealType2, Order2> const& cr2) {
+ using boost::math::trunc;
+ auto const numer = static_cast<typename fvar<RealType1, Order1>::root_type>(cr1);
+ auto const denom = static_cast<typename fvar<RealType2, Order2>::root_type>(cr2);
+ return cr1 - cr2 * trunc(numer / denom);
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> round(fvar<RealType, Order> const& cr) {
+ using boost::math::round;
+ return fvar<RealType, Order>(round(static_cast<typename fvar<RealType, Order>::root_type>(cr)));
+}
+
+template <typename RealType, size_t Order>
+int iround(fvar<RealType, Order> const& cr) {
+ using boost::math::iround;
+ return iround(static_cast<typename fvar<RealType, Order>::root_type>(cr));
+}
+
+template <typename RealType, size_t Order>
+long lround(fvar<RealType, Order> const& cr) {
+ using boost::math::lround;
+ return lround(static_cast<typename fvar<RealType, Order>::root_type>(cr));
+}
+
+template <typename RealType, size_t Order>
+long long llround(fvar<RealType, Order> const& cr) {
+ using boost::math::llround;
+ return llround(static_cast<typename fvar<RealType, Order>::root_type>(cr));
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> trunc(fvar<RealType, Order> const& cr) {
+ using boost::math::trunc;
+ return fvar<RealType, Order>(trunc(static_cast<typename fvar<RealType, Order>::root_type>(cr)));
+}
+
+template <typename RealType, size_t Order>
+long double truncl(fvar<RealType, Order> const& cr) {
+ using std::truncl;
+ return truncl(static_cast<typename fvar<RealType, Order>::root_type>(cr));
+}
+
+template <typename RealType, size_t Order>
+int itrunc(fvar<RealType, Order> const& cr) {
+ using boost::math::itrunc;
+ return itrunc(static_cast<typename fvar<RealType, Order>::root_type>(cr));
+}
+
+template <typename RealType, size_t Order>
+long long lltrunc(fvar<RealType, Order> const& cr) {
+ using boost::math::lltrunc;
+ return lltrunc(static_cast<typename fvar<RealType, Order>::root_type>(cr));
+}
+
+template <typename RealType, size_t Order>
+std::ostream& operator<<(std::ostream& out, fvar<RealType, Order> const& cr) {
+ out << "depth(" << cr.depth << ")(" << cr.v.front();
+ for (size_t i = 1; i <= Order; ++i)
+ out << ',' << cr.v[i];
+ return out << ')';
+}
+
+// Additional functions
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> acos(fvar<RealType, Order> const& cr) {
+ using std::acos;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = acos(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto x = make_fvar<root_type, order - 1>(static_cast<root_type>(cr));
+ auto const d1 = sqrt((x *= x).negate() += 1).inverse().negate(); // acos'(x) = -1 / sqrt(1-x*x).
+ return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> acosh(fvar<RealType, Order> const& cr) {
+ using boost::math::acosh;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = acosh(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto x = make_fvar<root_type, order - 1>(static_cast<root_type>(cr));
+ auto const d1 = sqrt((x *= x) -= 1).inverse(); // acosh'(x) = 1 / sqrt(x*x-1).
+ return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> asinh(fvar<RealType, Order> const& cr) {
+ using boost::math::asinh;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = asinh(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto x = make_fvar<root_type, order - 1>(static_cast<root_type>(cr));
+ auto const d1 = sqrt((x *= x) += 1).inverse(); // asinh'(x) = 1 / sqrt(x*x+1).
+ return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> atanh(fvar<RealType, Order> const& cr) {
+ using boost::math::atanh;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = atanh(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto x = make_fvar<root_type, order - 1>(static_cast<root_type>(cr));
+ auto const d1 = ((x *= x).negate() += 1).inverse(); // atanh'(x) = 1 / (1-x*x)
+ return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> cosh(fvar<RealType, Order> const& cr) {
+ BOOST_MATH_STD_USING
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = cosh(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ root_type const derivatives[2]{d0, sinh(static_cast<root_type>(cr))};
+ return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 1]; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> digamma(fvar<RealType, Order> const& cr) {
+ using boost::math::digamma;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const x = static_cast<root_type>(cr);
+ root_type const d0 = digamma(x);
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ static_assert(order <= static_cast<size_t>(std::numeric_limits<int>::max()),
+ "order exceeds maximum derivative for boost::math::polygamma().");
+ return cr.apply_derivatives(
+ order, [&x, &d0](size_t i) { return i ? boost::math::polygamma(static_cast<int>(i), x) : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> erf(fvar<RealType, Order> const& cr) {
+ using boost::math::erf;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = erf(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto x = make_fvar<root_type, order - 1>(static_cast<root_type>(cr)); // d1 = 2/sqrt(pi)*exp(-x*x)
+ auto const d1 = 2 * constants::one_div_root_pi<root_type>() * exp((x *= x).negate());
+ return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> erfc(fvar<RealType, Order> const& cr) {
+ using boost::math::erfc;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = erfc(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ auto x = make_fvar<root_type, order - 1>(static_cast<root_type>(cr)); // erfc'(x) = -erf'(x)
+ auto const d1 = -2 * constants::one_div_root_pi<root_type>() * exp((x *= x).negate());
+ return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> lambert_w0(fvar<RealType, Order> const& cr) {
+ using std::exp;
+ using boost::math::lambert_w0;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type derivatives[order + 1];
+ *derivatives = lambert_w0(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(*derivatives);
+ else {
+ root_type const expw = exp(*derivatives);
+ derivatives[1] = 1 / (static_cast<root_type>(cr) + expw);
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 1)
+ return cr.apply_derivatives_nonhorner(order, [&derivatives](size_t i) { return derivatives[i]; });
+ else {
+ using diff_t = typename std::array<RealType, Order + 1>::difference_type;
+ root_type d1powers = derivatives[1] * derivatives[1];
+ root_type const x = derivatives[1] * expw;
+ derivatives[2] = d1powers * (-1 - x);
+ std::array<root_type, order> coef{{-1, -1}}; // as in derivatives[2].
+ for (size_t n = 3; n <= order; ++n) {
+ coef[n - 1] = coef[n - 2] * -static_cast<root_type>(2 * n - 3);
+ for (size_t j = n - 2; j != 0; --j)
+ (coef[j] *= -static_cast<root_type>(n - 1)) -= (n + j - 2) * coef[j - 1];
+ coef[0] *= -static_cast<root_type>(n - 1);
+ d1powers *= derivatives[1];
+ derivatives[n] =
+ d1powers * std::accumulate(coef.crend() - diff_t(n - 1),
+ coef.crend(),
+ coef[n - 1],
+ [&x](root_type const& a, root_type const& b) { return a * x + b; });
+ }
+ return cr.apply_derivatives_nonhorner(order, [&derivatives](size_t i) { return derivatives[i]; });
+ }
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> lgamma(fvar<RealType, Order> const& cr) {
+ using std::lgamma;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const x = static_cast<root_type>(cr);
+ root_type const d0 = lgamma(x);
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ static_assert(order <= static_cast<size_t>(std::numeric_limits<int>::max()) + 1,
+ "order exceeds maximum derivative for boost::math::polygamma().");
+ return cr.apply_derivatives(
+ order, [&x, &d0](size_t i) { return i ? boost::math::polygamma(static_cast<int>(i - 1), x) : d0; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> sinc(fvar<RealType, Order> const& cr) {
+ if (cr != 0)
+ return sin(cr) / cr;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type taylor[order + 1]{1}; // sinc(0) = 1
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(*taylor);
+ else {
+ for (size_t n = 2; n <= order; n += 2)
+ taylor[n] = (1 - static_cast<int>(n & 2)) / factorial<root_type>(static_cast<unsigned>(n + 1));
+ return cr.apply_coefficients_nonhorner(order, [&taylor](size_t i) { return taylor[i]; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> sinh(fvar<RealType, Order> const& cr) {
+ BOOST_MATH_STD_USING
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ root_type const d0 = sinh(static_cast<root_type>(cr));
+ if BOOST_AUTODIFF_IF_CONSTEXPR (fvar<RealType, Order>::order_sum == 0)
+ return fvar<RealType, Order>(d0);
+ else {
+ root_type const derivatives[2]{d0, cosh(static_cast<root_type>(cr))};
+ return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 1]; });
+ }
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> tanh(fvar<RealType, Order> const& cr) {
+ fvar<RealType, Order> retval = exp(cr * 2);
+ fvar<RealType, Order> const denom = retval + 1;
+ (retval -= 1) /= denom;
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> tgamma(fvar<RealType, Order> const& cr) {
+ using std::tgamma;
+ using root_type = typename fvar<RealType, Order>::root_type;
+ constexpr size_t order = fvar<RealType, Order>::order_sum;
+ if BOOST_AUTODIFF_IF_CONSTEXPR (order == 0)
+ return fvar<RealType, Order>(tgamma(static_cast<root_type>(cr)));
+ else {
+ if (cr < 0)
+ return constants::pi<root_type>() / (sin(constants::pi<root_type>() * cr) * tgamma(1 - cr));
+ return exp(lgamma(cr)).set_root(tgamma(static_cast<root_type>(cr)));
+ }
+}
+
+} // namespace detail
+} // namespace autodiff_v1
+} // namespace differentiation
+} // namespace math
+} // namespace boost
+
+namespace std {
+
+// boost::math::tools::digits<RealType>() is handled by this std::numeric_limits<> specialization,
+// and similarly for max_value, min_value, log_max_value, log_min_value, and epsilon.
+template <typename RealType, size_t Order>
+class numeric_limits<boost::math::differentiation::detail::fvar<RealType, Order>>
+ : public numeric_limits<typename boost::math::differentiation::detail::fvar<RealType, Order>::root_type> {
+};
+
+} // namespace std
+
+namespace boost {
+namespace math {
+namespace tools {
+namespace detail {
+
+template <typename RealType, std::size_t Order>
+using autodiff_fvar_type = differentiation::detail::fvar<RealType, Order>;
+
+template <typename RealType, std::size_t Order>
+using autodiff_root_type = typename autodiff_fvar_type<RealType, Order>::root_type;
+} // namespace detail
+
+// See boost/math/tools/promotion.hpp
+template <typename RealType0, size_t Order0, typename RealType1, size_t Order1>
+struct promote_args_2<detail::autodiff_fvar_type<RealType0, Order0>,
+ detail::autodiff_fvar_type<RealType1, Order1>> {
+ using type = detail::autodiff_fvar_type<typename promote_args_2<RealType0, RealType1>::type,
+#ifndef BOOST_NO_CXX14_CONSTEXPR
+ (std::max)(Order0, Order1)>;
+#else
+ Order0<Order1 ? Order1 : Order0>;
+#endif
+};
+
+template <typename RealType, size_t Order>
+struct promote_args<detail::autodiff_fvar_type<RealType, Order>> {
+ using type = detail::autodiff_fvar_type<typename promote_args<RealType>::type, Order>;
+};
+
+template <typename RealType0, size_t Order0, typename RealType1>
+struct promote_args_2<detail::autodiff_fvar_type<RealType0, Order0>, RealType1> {
+ using type = detail::autodiff_fvar_type<typename promote_args_2<RealType0, RealType1>::type, Order0>;
+};
+
+template <typename RealType0, typename RealType1, size_t Order1>
+struct promote_args_2<RealType0, detail::autodiff_fvar_type<RealType1, Order1>> {
+ using type = detail::autodiff_fvar_type<typename promote_args_2<RealType0, RealType1>::type, Order1>;
+};
+
+template <typename destination_t, typename RealType, std::size_t Order>
+inline BOOST_MATH_CONSTEXPR destination_t real_cast(detail::autodiff_fvar_type<RealType, Order> const& from_v)
+ BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(destination_t) && BOOST_MATH_IS_FLOAT(RealType)) {
+ return real_cast<destination_t>(static_cast<detail::autodiff_root_type<RealType, Order>>(from_v));
+}
+
+} // namespace tools
+
+namespace policies {
+
+template <class Policy, std::size_t Order>
+using fvar_t = differentiation::detail::fvar<Policy, Order>;
+template <class Policy, std::size_t Order>
+struct evaluation<fvar_t<float, Order>, Policy> {
+ using type = fvar_t<typename conditional<Policy::promote_float_type::value, double, float>::type, Order>;
+};
+
+template <class Policy, std::size_t Order>
+struct evaluation<fvar_t<double, Order>, Policy> {
+ using type =
+ fvar_t<typename conditional<Policy::promote_double_type::value, long double, double>::type, Order>;
+};
+
+} // namespace policies
+} // namespace math
+} // namespace boost
+
+#ifdef BOOST_NO_CXX17_IF_CONSTEXPR
+#include "autodiff_cpp11.hpp"
+#endif
+
+#endif // BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP
diff --git a/boost/math/differentiation/autodiff_cpp11.hpp b/boost/math/differentiation/autodiff_cpp11.hpp
new file mode 100644
index 0000000000..42140a4824
--- /dev/null
+++ b/boost/math/differentiation/autodiff_cpp11.hpp
@@ -0,0 +1,383 @@
+// Copyright Matthew Pulver 2018 - 2019.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+
+// Contributors:
+// * Kedar R. Bhat - C++11 compatibility.
+
+// Notes:
+// * Any changes to this file should always be downstream from autodiff.cpp.
+// C++17 is a higher-level language and is easier to maintain. For example, a number of functions which are
+// lucidly read in autodiff.cpp are forced to be split into multiple structs/functions in this file for
+// C++11.
+// * Use of typename RootType and SizeType is a hack to prevent Visual Studio 2015 from compiling functions
+// that are never called, that would otherwise produce compiler errors. Also forces functions to be inline.
+
+#ifndef BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP
+#error \
+ "Do not #include this file directly. This should only be #included by autodiff.hpp for C++11 compatibility."
+#endif
+
+#include <boost/mp11/integer_sequence.hpp>
+
+namespace boost {
+namespace math {
+namespace differentiation {
+inline namespace autodiff_v1 {
+namespace detail {
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order>::fvar(root_type const& ca, bool const is_variable) {
+ fvar_cpp11(is_fvar<RealType>{}, ca, is_variable);
+}
+
+template <typename RealType, size_t Order>
+template <typename RootType>
+void fvar<RealType, Order>::fvar_cpp11(std::true_type, RootType const& ca, bool const is_variable) {
+ v.front() = RealType(ca, is_variable);
+ if (0 < Order)
+ std::fill(v.begin() + 1, v.end(), static_cast<RealType>(0));
+}
+
+template <typename RealType, size_t Order>
+template <typename RootType>
+void fvar<RealType, Order>::fvar_cpp11(std::false_type, RootType const& ca, bool const is_variable) {
+ v.front() = ca;
+ if (0 < Order) {
+ v[1] = static_cast<root_type>(static_cast<int>(is_variable));
+ if (1 < Order)
+ std::fill(v.begin() + 2, v.end(), static_cast<RealType>(0));
+ }
+}
+
+template <typename RealType, size_t Order>
+template <typename... Orders>
+get_type_at<RealType, sizeof...(Orders)> fvar<RealType, Order>::at_cpp11(std::true_type,
+ size_t order,
+ Orders...) const {
+ return v.at(order);
+}
+
+template <typename RealType, size_t Order>
+template <typename... Orders>
+get_type_at<RealType, sizeof...(Orders)> fvar<RealType, Order>::at_cpp11(std::false_type,
+ size_t order,
+ Orders... orders) const {
+ return v.at(order).at(orders...);
+}
+
+// Can throw "std::out_of_range: array::at: __n (which is 7) >= _Nm (which is 7)"
+template <typename RealType, size_t Order>
+template <typename... Orders>
+get_type_at<RealType, sizeof...(Orders)> fvar<RealType, Order>::at(size_t order, Orders... orders) const {
+ return at_cpp11(std::integral_constant<bool, sizeof...(orders) == 0>{}, order, orders...);
+}
+
+template <typename T, typename... Ts>
+constexpr T product(Ts...) {
+ return static_cast<T>(1);
+}
+
+template <typename T, typename... Ts>
+constexpr T product(T factor, Ts... factors) {
+ return factor * product<T>(factors...);
+}
+
+// Can throw "std::out_of_range: array::at: __n (which is 7) >= _Nm (which is 7)"
+template <typename RealType, size_t Order>
+template <typename... Orders>
+get_type_at<fvar<RealType, Order>, sizeof...(Orders)> fvar<RealType, Order>::derivative(
+ Orders... orders) const {
+ static_assert(sizeof...(Orders) <= depth,
+ "Number of parameters to derivative(...) cannot exceed fvar::depth.");
+ return at(static_cast<size_t>(orders)...) *
+ product(boost::math::factorial<root_type>(static_cast<unsigned>(orders))...);
+}
+
+template <typename RootType, typename Func>
+class Curry {
+ Func const& f_;
+ size_t const i_;
+
+ public:
+ template <typename SizeType> // typename SizeType to force inline constructor.
+ Curry(Func const& f, SizeType i) : f_(f), i_(static_cast<std::size_t>(i)) {}
+ template <typename... Indices>
+ RootType operator()(Indices... indices) const {
+ using unsigned_t = typename std::make_unsigned<typename std::common_type<Indices>::type...>::type;
+ return f_(i_, static_cast<unsigned_t>(indices)...);
+ }
+};
+
+template <typename RealType, size_t Order>
+template <typename Func, typename Fvar, typename... Fvars>
+promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_coefficients(
+ size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+ size_t i = order < order_sum ? order : order_sum;
+ using return_type = promote<fvar<RealType, Order>, Fvar, Fvars...>;
+ return_type accumulator = cr.apply_coefficients(
+ order - i, Curry<typename return_type::root_type, Func>(f, i), std::forward<Fvars>(fvars)...);
+ while (i--)
+ (accumulator *= epsilon) += cr.apply_coefficients(
+ order - i, Curry<typename return_type::root_type, Func>(f, i), std::forward<Fvars>(fvars)...);
+ return accumulator;
+}
+
+template <typename RealType, size_t Order>
+template <typename Func, typename Fvar, typename... Fvars>
+promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_coefficients_nonhorner(
+ size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+ fvar<RealType, Order> epsilon_i = fvar<RealType, Order>(1); // epsilon to the power of i
+ using return_type = promote<fvar<RealType, Order>, Fvar, Fvars...>;
+ return_type accumulator = cr.apply_coefficients_nonhorner(
+ order, Curry<typename return_type::root_type, Func>(f, 0), std::forward<Fvars>(fvars)...);
+ size_t const i_max = order < order_sum ? order : order_sum;
+ for (size_t i = 1; i <= i_max; ++i) {
+ epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0);
+ accumulator += epsilon_i.epsilon_multiply(
+ i,
+ 0,
+ cr.apply_coefficients_nonhorner(
+ order - i, Curry<typename return_type::root_type, Func>(f, i), std::forward<Fvars>(fvars)...),
+ 0,
+ 0);
+ }
+ return accumulator;
+}
+
+template <typename RealType, size_t Order>
+template <typename Func, typename Fvar, typename... Fvars>
+promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_derivatives(
+ size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+ size_t i = order < order_sum ? order : order_sum;
+ using return_type = promote<fvar<RealType, Order>, Fvar, Fvars...>;
+ return_type accumulator =
+ cr.apply_derivatives(
+ order - i, Curry<typename return_type::root_type, Func>(f, i), std::forward<Fvars>(fvars)...) /
+ factorial<root_type>(static_cast<unsigned>(i));
+ while (i--)
+ (accumulator *= epsilon) +=
+ cr.apply_derivatives(
+ order - i, Curry<typename return_type::root_type, Func>(f, i), std::forward<Fvars>(fvars)...) /
+ factorial<root_type>(static_cast<unsigned>(i));
+ return accumulator;
+}
+
+template <typename RealType, size_t Order>
+template <typename Func, typename Fvar, typename... Fvars>
+promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_derivatives_nonhorner(
+ size_t const order,
+ Func const& f,
+ Fvar const& cr,
+ Fvars&&... fvars) const {
+ fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
+ fvar<RealType, Order> epsilon_i = fvar<RealType, Order>(1); // epsilon to the power of i
+ using return_type = promote<fvar<RealType, Order>, Fvar, Fvars...>;
+ return_type accumulator = cr.apply_derivatives_nonhorner(
+ order, Curry<typename return_type::root_type, Func>(f, 0), std::forward<Fvars>(fvars)...);
+ size_t const i_max = order < order_sum ? order : order_sum;
+ for (size_t i = 1; i <= i_max; ++i) {
+ epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0);
+ accumulator += epsilon_i.epsilon_multiply(
+ i,
+ 0,
+ cr.apply_derivatives_nonhorner(
+ order - i, Curry<typename return_type::root_type, Func>(f, i), std::forward<Fvars>(fvars)...) /
+ factorial<root_type>(static_cast<unsigned>(i)),
+ 0,
+ 0);
+ }
+ return accumulator;
+}
+
+template <typename RealType, size_t Order>
+template <typename SizeType>
+fvar<RealType, Order> fvar<RealType, Order>::epsilon_multiply_cpp11(std::true_type,
+ SizeType z0,
+ size_t isum0,
+ fvar<RealType, Order> const& cr,
+ size_t z1,
+ size_t isum1) const {
+ size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0;
+ size_t const m1 = order_sum + isum1 < Order + z1 ? Order + z1 - (order_sum + isum1) : 0;
+ size_t const i_max = m0 + m1 < Order ? Order - (m0 + m1) : 0;
+ fvar<RealType, Order> retval = fvar<RealType, Order>();
+ for (size_t i = 0, j = Order; i <= i_max; ++i, --j)
+ retval.v[j] = epsilon_inner_product(z0, isum0, m0, cr, z1, isum1, m1, j);
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+template <typename SizeType>
+fvar<RealType, Order> fvar<RealType, Order>::epsilon_multiply_cpp11(std::false_type,
+ SizeType z0,
+ size_t isum0,
+ fvar<RealType, Order> const& cr,
+ size_t z1,
+ size_t isum1) const {
+ using ssize_t = typename std::make_signed<std::size_t>::type;
+ RealType const zero(0);
+ size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0;
+ size_t const m1 = order_sum + isum1 < Order + z1 ? Order + z1 - (order_sum + isum1) : 0;
+ size_t const i_max = m0 + m1 < Order ? Order - (m0 + m1) : 0;
+ fvar<RealType, Order> retval = fvar<RealType, Order>();
+ for (size_t i = 0, j = Order; i <= i_max; ++i, --j)
+ retval.v[j] = std::inner_product(
+ v.cbegin() + ssize_t(m0), v.cend() - ssize_t(i + m1), cr.v.crbegin() + ssize_t(i + m0), zero);
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fvar<RealType, Order>::epsilon_multiply(size_t z0,
+ size_t isum0,
+ fvar<RealType, Order> const& cr,
+ size_t z1,
+ size_t isum1) const {
+ return epsilon_multiply_cpp11(is_fvar<RealType>{}, z0, isum0, cr, z1, isum1);
+}
+
+template <typename RealType, size_t Order>
+template <typename SizeType>
+fvar<RealType, Order> fvar<RealType, Order>::epsilon_multiply_cpp11(std::true_type,
+ SizeType z0,
+ size_t isum0,
+ root_type const& ca) const {
+ fvar<RealType, Order> retval(*this);
+ size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0;
+ for (size_t i = m0; i <= Order; ++i)
+ retval.v[i] = retval.v[i].epsilon_multiply(z0, isum0 + i, ca);
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+template <typename SizeType>
+fvar<RealType, Order> fvar<RealType, Order>::epsilon_multiply_cpp11(std::false_type,
+ SizeType z0,
+ size_t isum0,
+ root_type const& ca) const {
+ fvar<RealType, Order> retval(*this);
+ size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0;
+ for (size_t i = m0; i <= Order; ++i)
+ if (retval.v[i] != static_cast<RealType>(0))
+ retval.v[i] *= ca;
+ return retval;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order> fvar<RealType, Order>::epsilon_multiply(size_t z0,
+ size_t isum0,
+ root_type const& ca) const {
+ return epsilon_multiply_cpp11(is_fvar<RealType>{}, z0, isum0, ca);
+}
+
+template <typename RealType, size_t Order>
+template <typename RootType>
+fvar<RealType, Order>& fvar<RealType, Order>::multiply_assign_by_root_type_cpp11(std::true_type,
+ bool is_root,
+ RootType const& ca) {
+ auto itr = v.begin();
+ itr->multiply_assign_by_root_type(is_root, ca);
+ for (++itr; itr != v.end(); ++itr)
+ itr->multiply_assign_by_root_type(false, ca);
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+template <typename RootType>
+fvar<RealType, Order>& fvar<RealType, Order>::multiply_assign_by_root_type_cpp11(std::false_type,
+ bool is_root,
+ RootType const& ca) {
+ auto itr = v.begin();
+ if (is_root || *itr != 0)
+ *itr *= ca; // Skip multiplication of 0 by ca=inf to avoid nan, except when is_root.
+ for (++itr; itr != v.end(); ++itr)
+ if (*itr != 0)
+ *itr *= ca;
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order>& fvar<RealType, Order>::multiply_assign_by_root_type(bool is_root,
+ root_type const& ca) {
+ return multiply_assign_by_root_type_cpp11(is_fvar<RealType>{}, is_root, ca);
+}
+
+template <typename RealType, size_t Order>
+template <typename RootType>
+fvar<RealType, Order>& fvar<RealType, Order>::negate_cpp11(std::true_type, RootType const&) {
+ std::for_each(v.begin(), v.end(), [](RealType& r) { r.negate(); });
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+template <typename RootType>
+fvar<RealType, Order>& fvar<RealType, Order>::negate_cpp11(std::false_type, RootType const&) {
+ std::for_each(v.begin(), v.end(), [](RealType& a) { a = -a; });
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order>& fvar<RealType, Order>::negate() {
+ return negate_cpp11(is_fvar<RealType>{}, static_cast<root_type>(*this));
+}
+
+template <typename RealType, size_t Order>
+template <typename RootType>
+fvar<RealType, Order>& fvar<RealType, Order>::set_root_cpp11(std::true_type, RootType const& root) {
+ v.front().set_root(root);
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+template <typename RootType>
+fvar<RealType, Order>& fvar<RealType, Order>::set_root_cpp11(std::false_type, RootType const& root) {
+ v.front() = root;
+ return *this;
+}
+
+template <typename RealType, size_t Order>
+fvar<RealType, Order>& fvar<RealType, Order>::set_root(root_type const& root) {
+ return set_root_cpp11(is_fvar<RealType>{}, root);
+}
+
+template <typename RealType, size_t Order, size_t... Is>
+auto make_fvar_for_tuple(mp11::index_sequence<Is...>, RealType const& ca)
+ -> decltype(make_fvar<RealType, zero<Is>::value..., Order>(ca)) {
+ return make_fvar<RealType, zero<Is>::value..., Order>(ca);
+}
+
+template <typename RealType, size_t... Orders, size_t... Is, typename... RealTypes>
+auto make_ftuple_impl(mp11::index_sequence<Is...>, RealTypes const&... ca)
+ -> decltype(std::make_tuple(make_fvar_for_tuple<RealType, Orders>(mp11::make_index_sequence<Is>{},
+ ca)...)) {
+ return std::make_tuple(make_fvar_for_tuple<RealType, Orders>(mp11::make_index_sequence<Is>{}, ca)...);
+}
+
+} // namespace detail
+
+template <typename RealType, size_t... Orders, typename... RealTypes>
+auto make_ftuple(RealTypes const&... ca)
+ -> decltype(detail::make_ftuple_impl<RealType, Orders...>(mp11::index_sequence_for<RealTypes...>{},
+ ca...)) {
+ static_assert(sizeof...(Orders) == sizeof...(RealTypes),
+ "Number of Orders must match number of function parameters.");
+ return detail::make_ftuple_impl<RealType, Orders...>(mp11::index_sequence_for<RealTypes...>{}, ca...);
+}
+
+} // namespace autodiff_v1
+} // namespace differentiation
+} // namespace math
+} // namespace boost
diff --git a/boost/math/interpolators/cardinal_quadratic_b_spline.hpp b/boost/math/interpolators/cardinal_quadratic_b_spline.hpp
new file mode 100644
index 0000000000..a5b150f2f1
--- /dev/null
+++ b/boost/math/interpolators/cardinal_quadratic_b_spline.hpp
@@ -0,0 +1,57 @@
+// Copyright Nick Thompson, 2019
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MATH_INTERPOLATORS_CARDINAL_QUADRATIC_B_SPLINE_HPP
+#define BOOST_MATH_INTERPOLATORS_CARDINAL_QUADRATIC_B_SPLINE_HPP
+#include <memory>
+#include <boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp>
+
+
+namespace boost{ namespace math{ namespace interpolators {
+
+template <class Real>
+class cardinal_quadratic_b_spline
+{
+public:
+ // If you don't know the value of the derivative at the endpoints, leave them as nans and the routine will estimate them.
+ // y[0] = y(a), y[n - 1] = y(b), step_size = (b - a)/(n -1).
+ cardinal_quadratic_b_spline(const Real* const y,
+ size_t n,
+ Real t0 /* initial time, left endpoint */,
+ Real h /*spacing, stepsize*/,
+ Real left_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN(),
+ Real right_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN())
+ : impl_(std::make_shared<detail::cardinal_quadratic_b_spline_detail<Real>>(y, n, t0, h, left_endpoint_derivative, right_endpoint_derivative))
+ {}
+
+ // Oh the bizarre error messages if we template this on a RandomAccessContainer:
+ cardinal_quadratic_b_spline(std::vector<Real> const & y,
+ Real t0 /* initial time, left endpoint */,
+ Real h /*spacing, stepsize*/,
+ Real left_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN(),
+ Real right_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN())
+ : impl_(std::make_shared<detail::cardinal_quadratic_b_spline_detail<Real>>(y.data(), y.size(), t0, h, left_endpoint_derivative, right_endpoint_derivative))
+ {}
+
+
+ Real operator()(Real t) const {
+ return impl_->operator()(t);
+ }
+
+ Real prime(Real t) const {
+ return impl_->prime(t);
+ }
+
+ Real t_max() const {
+ return impl_->t_max();
+ }
+
+private:
+ std::shared_ptr<detail::cardinal_quadratic_b_spline_detail<Real>> impl_;
+};
+
+}}}
+#endif
diff --git a/boost/math/interpolators/catmull_rom.hpp b/boost/math/interpolators/catmull_rom.hpp
index 05ad666de2..20207871db 100644
--- a/boost/math/interpolators/catmull_rom.hpp
+++ b/boost/math/interpolators/catmull_rom.hpp
@@ -13,6 +13,25 @@
#include <vector>
#include <algorithm>
#include <iterator>
+#include <boost/config.hpp>
+
+namespace std_workaround {
+
+#if defined(__cpp_lib_nonmember_container_access) || (defined(BOOST_MSVC) && (BOOST_MSVC >= 1900))
+ using std::size;
+#else
+ template <class C>
+ inline BOOST_CONSTEXPR std::size_t size(const C& c)
+ {
+ return c.size();
+ }
+ template <class T, std::size_t N>
+ inline BOOST_CONSTEXPR std::size_t size(const T(&array)[N]) BOOST_NOEXCEPT
+ {
+ return N;
+ }
+#endif
+}
namespace boost{ namespace math{
@@ -22,7 +41,7 @@ namespace boost{ namespace math{
typename Point::value_type alpha_distance(Point const & p1, Point const & p2, typename Point::value_type alpha)
{
using std::pow;
- using std::size;
+ using std_workaround::size;
typename Point::value_type dsq = 0;
for (size_t i = 0; i < size(p1); ++i)
{
@@ -33,44 +52,45 @@ namespace boost{ namespace math{
}
}
-template <class Point>
+template <class Point, class RandomAccessContainer = std::vector<Point> >
class catmull_rom
{
+ typedef typename Point::value_type value_type;
public:
- catmull_rom(std::vector<Point>&& points, bool closed = false, typename Point::value_type alpha = (typename Point::value_type) 1/ (typename Point::value_type) 2);
+ catmull_rom(RandomAccessContainer&& points, bool closed = false, value_type alpha = (value_type) 1/ (value_type) 2);
- catmull_rom(std::initializer_list<Point> l, bool closed = false, typename Point::value_type alpha = (typename Point::value_type) 1/ (typename Point::value_type) 2) : catmull_rom(std::vector<Point>(l), closed, alpha) {}
+ catmull_rom(std::initializer_list<Point> l, bool closed = false, value_type alpha = (value_type) 1/ (value_type) 2) : catmull_rom<Point, RandomAccessContainer>(RandomAccessContainer(l), closed, alpha) {}
- typename Point::value_type max_parameter() const
+ value_type max_parameter() const
{
return m_max_s;
}
- typename Point::value_type parameter_at_point(size_t i) const
+ value_type parameter_at_point(size_t i) const
{
return m_s[i+1];
}
- Point operator()(const typename Point::value_type s) const;
+ Point operator()(const value_type s) const;
- Point prime(const typename Point::value_type s) const;
+ Point prime(const value_type s) const;
- std::vector<Point>&& get_points()
+ RandomAccessContainer&& get_points()
{
return std::move(m_pnts);
}
private:
- std::vector<Point> m_pnts;
- std::vector<typename Point::value_type> m_s;
- typename Point::value_type m_max_s;
+ RandomAccessContainer m_pnts;
+ std::vector<value_type> m_s;
+ value_type m_max_s;
};
-template<class Point>
-catmull_rom<Point>::catmull_rom(std::vector<Point>&& points, bool closed, typename Point::value_type alpha) : m_pnts(std::move(points))
+template<class Point, class RandomAccessContainer >
+catmull_rom<Point, RandomAccessContainer>::catmull_rom(RandomAccessContainer&& points, bool closed, typename Point::value_type alpha) : m_pnts(std::move(points))
{
- size_t num_pnts = m_pnts.size();
+ std::size_t num_pnts = m_pnts.size();
//std::cout << "Number of points = " << num_pnts << "\n";
if (num_pnts < 4)
{
@@ -90,7 +110,7 @@ catmull_rom<Point>::catmull_rom(std::vector<Point>&& points, bool closed, typena
m_pnts[num_pnts+2] = m_pnts[1];
auto tmp = m_pnts[num_pnts-1];
- for (int64_t i = num_pnts-1; i >= 0; --i)
+ for (std::ptrdiff_t i = num_pnts-1; i >= 0; --i)
{
m_pnts[i+1] = m_pnts[i];
}
@@ -122,10 +142,10 @@ catmull_rom<Point>::catmull_rom(std::vector<Point>&& points, bool closed, typena
}
-template<class Point>
-Point catmull_rom<Point>::operator()(const typename Point::value_type s) const
+template<class Point, class RandomAccessContainer >
+Point catmull_rom<Point, RandomAccessContainer>::operator()(const typename Point::value_type s) const
{
- using std::size;
+ using std_workaround::size;
if (s < 0 || s > m_max_s)
{
throw std::domain_error("Parameter outside bounds.");
@@ -182,10 +202,10 @@ Point catmull_rom<Point>::operator()(const typename Point::value_type s) const
return B1_or_C;
}
-template<class Point>
-Point catmull_rom<Point>::prime(const typename Point::value_type s) const
+template<class Point, class RandomAccessContainer >
+Point catmull_rom<Point, RandomAccessContainer>::prime(const typename Point::value_type s) const
{
- using std::size;
+ using std_workaround::size;
// https://math.stackexchange.com/questions/843595/how-can-i-calculate-the-derivative-of-a-catmull-rom-spline-with-nonuniform-param
// http://denkovacs.com/2016/02/catmull-rom-spline-derivatives/
if (s < 0 || s > m_max_s)
diff --git a/boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp b/boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp
new file mode 100644
index 0000000000..044ac72179
--- /dev/null
+++ b/boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp
@@ -0,0 +1,206 @@
+// Copyright Nick Thompson, 2019
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MATH_INTERPOLATORS_CARDINAL_QUADRATIC_B_SPLINE_DETAIL_HPP
+#define BOOST_MATH_INTERPOLATORS_CARDINAL_QUADRATIC_B_SPLINE_DETAIL_HPP
+#include <vector>
+
+namespace boost{ namespace math{ namespace interpolators{ namespace detail{
+
+template <class Real>
+Real b2_spline(Real x) {
+ using std::abs;
+ Real absx = abs(x);
+ if (absx < 1/Real(2))
+ {
+ Real y = absx - 1/Real(2);
+ Real z = absx + 1/Real(2);
+ return (2-y*y-z*z)/2;
+ }
+ if (absx < Real(3)/Real(2))
+ {
+ Real y = absx - Real(3)/Real(2);
+ return y*y/2;
+ }
+ return (Real) 0;
+}
+
+template <class Real>
+Real b2_spline_prime(Real x) {
+ if (x < 0) {
+ return -b2_spline_prime(-x);
+ }
+
+ if (x < 1/Real(2))
+ {
+ return -2*x;
+ }
+ if (x < Real(3)/Real(2))
+ {
+ return x - Real(3)/Real(2);
+ }
+ return (Real) 0;
+}
+
+
+template <class Real>
+class cardinal_quadratic_b_spline_detail
+{
+public:
+ // If you don't know the value of the derivative at the endpoints, leave them as nans and the routine will estimate them.
+ // y[0] = y(a), y[n -1] = y(b), step_size = (b - a)/(n -1).
+
+ cardinal_quadratic_b_spline_detail(const Real* const y,
+ size_t n,
+ Real t0 /* initial time, left endpoint */,
+ Real h /*spacing, stepsize*/,
+ Real left_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN(),
+ Real right_endpoint_derivative = std::numeric_limits<Real>::quiet_NaN())
+ {
+ if (h <= 0) {
+ throw std::logic_error("Spacing must be > 0.");
+ }
+ m_inv_h = 1/h;
+ m_t0 = t0;
+
+ if (n < 3) {
+ throw std::logic_error("The interpolator requires at least 3 points.");
+ }
+
+ using std::isnan;
+ Real a;
+ if (isnan(left_endpoint_derivative)) {
+ // http://web.media.mit.edu/~crtaylor/calculator.html
+ a = -3*y[0] + 4*y[1] - y[2];
+ }
+ else {
+ a = 2*h*left_endpoint_derivative;
+ }
+
+ Real b;
+ if (isnan(right_endpoint_derivative)) {
+ b = 3*y[n-1] - 4*y[n-2] + y[n-3];
+ }
+ else {
+ b = 2*h*right_endpoint_derivative;
+ }
+
+ m_alpha.resize(n + 2);
+
+ // Begin row reduction:
+ std::vector<Real> rhs(n + 2, std::numeric_limits<Real>::quiet_NaN());
+ std::vector<Real> super_diagonal(n + 2, std::numeric_limits<Real>::quiet_NaN());
+
+ rhs[0] = -a;
+ rhs[rhs.size() - 1] = b;
+
+ super_diagonal[0] = 0;
+
+ for(size_t i = 1; i < rhs.size() - 1; ++i) {
+ rhs[i] = 8*y[i - 1];
+ super_diagonal[i] = 1;
+ }
+
+ // Patch up 5-diagonal problem:
+ rhs[1] = (rhs[1] - rhs[0])/6;
+ super_diagonal[1] = Real(1)/Real(3);
+ // First two rows are now:
+ // 1 0 -1 | -2hy0'
+ // 0 1 1/3| (8y0+2hy0')/6
+
+
+ // Start traditional tridiagonal row reduction:
+ for (size_t i = 2; i < rhs.size() - 1; ++i) {
+ Real diagonal = 6 - super_diagonal[i - 1];
+ rhs[i] = (rhs[i] - rhs[i - 1])/diagonal;
+ super_diagonal[i] /= diagonal;
+ }
+
+ // 1 sd[n-1] 0 | rhs[n-1]
+ // 0 1 sd[n] | rhs[n]
+ // -1 0 1 | rhs[n+1]
+
+ rhs[n+1] = rhs[n+1] + rhs[n-1];
+ Real bottom_subdiagonal = super_diagonal[n-1];
+
+ // We're here:
+ // 1 sd[n-1] 0 | rhs[n-1]
+ // 0 1 sd[n] | rhs[n]
+ // 0 bs 1 | rhs[n+1]
+
+ rhs[n+1] = (rhs[n+1]-bottom_subdiagonal*rhs[n])/(1-bottom_subdiagonal*super_diagonal[n]);
+
+ m_alpha[n+1] = rhs[n+1];
+ for (size_t i = n; i > 0; --i) {
+ m_alpha[i] = rhs[i] - m_alpha[i+1]*super_diagonal[i];
+ }
+ m_alpha[0] = m_alpha[2] + rhs[0];
+ }
+
+ Real operator()(Real t) const {
+ if (t < m_t0 || t > m_t0 + (m_alpha.size()-2)/m_inv_h) {
+ const char* err_msg = "Tried to evaluate the cardinal quadratic b-spline outside the domain of of interpolation; extrapolation does not work.";
+ throw std::domain_error(err_msg);
+ }
+ // Let k, γ be defined via t = t0 + kh + γh.
+ // Now find all j: |k-j+1+γ|< 3/2, or, in other words
+ // j_min = ceil((t-t0)/h - 1/2)
+ // j_max = floor(t-t0)/h + 5/2)
+ using std::floor;
+ using std::ceil;
+ Real x = (t-m_t0)*m_inv_h;
+ size_t j_min = ceil(x - Real(1)/Real(2));
+ size_t j_max = ceil(x + Real(5)/Real(2));
+ if (j_max >= m_alpha.size()) {
+ j_max = m_alpha.size() - 1;
+ }
+
+ Real y = 0;
+ x += 1;
+ for (size_t j = j_min; j <= j_max; ++j) {
+ y += m_alpha[j]*detail::b2_spline(x - j);
+ }
+ return y;
+ }
+
+ Real prime(Real t) const {
+ if (t < m_t0 || t > m_t0 + (m_alpha.size()-2)/m_inv_h) {
+ const char* err_msg = "Tried to evaluate the cardinal quadratic b-spline outside the domain of of interpolation; extrapolation does not work.";
+ throw std::domain_error(err_msg);
+ }
+ // Let k, γ be defined via t = t0 + kh + γh.
+ // Now find all j: |k-j+1+γ|< 3/2, or, in other words
+ // j_min = ceil((t-t0)/h - 1/2)
+ // j_max = floor(t-t0)/h + 5/2)
+ using std::floor;
+ using std::ceil;
+ Real x = (t-m_t0)*m_inv_h;
+ size_t j_min = ceil(x - Real(1)/Real(2));
+ size_t j_max = ceil(x + Real(5)/Real(2));
+ if (j_max >= m_alpha.size()) {
+ j_max = m_alpha.size() - 1;
+ }
+
+ Real y = 0;
+ x += 1;
+ for (size_t j = j_min; j <= j_max; ++j) {
+ y += m_alpha[j]*detail::b2_spline_prime(x - j);
+ }
+ return y*m_inv_h;
+ }
+
+ Real t_max() const {
+ return m_t0 + (m_alpha.size()-3)/m_inv_h;
+ }
+
+private:
+ std::vector<Real> m_alpha;
+ Real m_inv_h;
+ Real m_t0;
+};
+
+}}}}
+#endif
diff --git a/boost/math/interpolators/detail/vector_barycentric_rational_detail.hpp b/boost/math/interpolators/detail/vector_barycentric_rational_detail.hpp
new file mode 100644
index 0000000000..2f8d177a35
--- /dev/null
+++ b/boost/math/interpolators/detail/vector_barycentric_rational_detail.hpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright Nick Thompson, 2019
+ * Use, modification and distribution are subject to the
+ * Boost Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_MATH_INTERPOLATORS_VECTOR_BARYCENTRIC_RATIONAL_DETAIL_HPP
+#define BOOST_MATH_INTERPOLATORS_VECTOR_BARYCENTRIC_RATIONAL_DETAIL_HPP
+
+#include <vector>
+#include <utility> // for std::move
+#include <boost/assert.hpp>
+
+namespace boost{ namespace math{ namespace detail{
+
+template <class TimeContainer, class SpaceContainer>
+class vector_barycentric_rational_imp
+{
+public:
+ using Real = typename TimeContainer::value_type;
+ using Point = typename SpaceContainer::value_type;
+
+ vector_barycentric_rational_imp(TimeContainer&& t, SpaceContainer&& y, size_t approximation_order);
+
+ void operator()(Point& p, Real t) const;
+
+ void eval_with_prime(Point& x, Point& dxdt, Real t) const;
+
+ // The barycentric weights are only interesting to the unit tests:
+ Real weight(size_t i) const { return w_[i]; }
+
+private:
+
+ void calculate_weights(size_t approximation_order);
+
+ TimeContainer t_;
+ SpaceContainer y_;
+ TimeContainer w_;
+};
+
+template <class TimeContainer, class SpaceContainer>
+vector_barycentric_rational_imp<TimeContainer, SpaceContainer>::vector_barycentric_rational_imp(TimeContainer&& t, SpaceContainer&& y, size_t approximation_order)
+{
+ using Real = typename TimeContainer::value_type;
+ using std::numeric_limits;
+ t_ = std::move(t);
+ y_ = std::move(y);
+
+ BOOST_ASSERT_MSG(t_.size() == y_.size(), "There must be the same number of time points as space points.");
+ BOOST_ASSERT_MSG(approximation_order < y_.size(), "Approximation order must be < data length.");
+ for (size_t i = 1; i < t_.size(); ++i)
+ {
+ BOOST_ASSERT_MSG(t_[i] - t_[i-1] > (numeric_limits<Real>::min)(), "The abscissas must be listed in strictly increasing order t[0] < t[1] < ... < t[n-1].");
+ }
+ calculate_weights(approximation_order);
+}
+
+
+template<class TimeContainer, class SpaceContainer>
+void vector_barycentric_rational_imp<TimeContainer, SpaceContainer>::calculate_weights(size_t approximation_order)
+{
+ using Real = typename TimeContainer::value_type;
+ using std::abs;
+ int64_t n = t_.size();
+ w_.resize(n, Real(0));
+ for(int64_t k = 0; k < n; ++k)
+ {
+ int64_t i_min = (std::max)(k - (int64_t) approximation_order, (int64_t) 0);
+ int64_t i_max = k;
+ if (k >= n - (std::ptrdiff_t)approximation_order)
+ {
+ i_max = n - approximation_order - 1;
+ }
+
+ for(int64_t i = i_min; i <= i_max; ++i)
+ {
+ Real inv_product = 1;
+ int64_t j_max = (std::min)(static_cast<int64_t>(i + approximation_order), static_cast<int64_t>(n - 1));
+ for(int64_t j = i; j <= j_max; ++j)
+ {
+ if (j == k)
+ {
+ continue;
+ }
+ Real diff = t_[k] - t_[j];
+ inv_product *= diff;
+ }
+ if (i % 2 == 0)
+ {
+ w_[k] += 1/inv_product;
+ }
+ else
+ {
+ w_[k] -= 1/inv_product;
+ }
+ }
+ }
+}
+
+
+template<class TimeContainer, class SpaceContainer>
+void vector_barycentric_rational_imp<TimeContainer, SpaceContainer>::operator()(typename SpaceContainer::value_type& p, typename TimeContainer::value_type t) const
+{
+ using Real = typename TimeContainer::value_type;
+ for (auto & x : p)
+ {
+ x = Real(0);
+ }
+ Real denominator = 0;
+ for(size_t i = 0; i < t_.size(); ++i)
+ {
+ // See associated commentary in the scalar version of this function.
+ if (t == t_[i])
+ {
+ p = y_[i];
+ return;
+ }
+ Real x = w_[i]/(t - t_[i]);
+ for (decltype(p.size()) j = 0; j < p.size(); ++j)
+ {
+ p[j] += x*y_[i][j];
+ }
+ denominator += x;
+ }
+ for (decltype(p.size()) j = 0; j < p.size(); ++j)
+ {
+ p[j] /= denominator;
+ }
+ return;
+}
+
+template<class TimeContainer, class SpaceContainer>
+void vector_barycentric_rational_imp<TimeContainer, SpaceContainer>::eval_with_prime(typename SpaceContainer::value_type& x, typename SpaceContainer::value_type& dxdt, typename TimeContainer::value_type t) const
+{
+ using Point = typename SpaceContainer::value_type;
+ using Real = typename TimeContainer::value_type;
+ this->operator()(x, t);
+ Point numerator;
+ for (decltype(x.size()) i = 0; i < x.size(); ++i)
+ {
+ numerator[i] = 0;
+ }
+ Real denominator = 0;
+ for(decltype(t_.size()) i = 0; i < t_.size(); ++i)
+ {
+ if (t == t_[i])
+ {
+ Point sum;
+ for (decltype(x.size()) i = 0; i < x.size(); ++i)
+ {
+ sum[i] = 0;
+ }
+
+ for (decltype(t_.size()) j = 0; j < t_.size(); ++j)
+ {
+ if (j == i)
+ {
+ continue;
+ }
+ for (decltype(sum.size()) k = 0; k < sum.size(); ++k)
+ {
+ sum[k] += w_[j]*(y_[i][k] - y_[j][k])/(t_[i] - t_[j]);
+ }
+ }
+ for (decltype(sum.size()) k = 0; k < sum.size(); ++k)
+ {
+ dxdt[k] = -sum[k]/w_[i];
+ }
+ return;
+ }
+ Real tw = w_[i]/(t - t_[i]);
+ Point diff;
+ for (decltype(diff.size()) j = 0; j < diff.size(); ++j)
+ {
+ diff[j] = (x[j] - y_[i][j])/(t-t_[i]);
+ }
+ for (decltype(diff.size()) j = 0; j < diff.size(); ++j)
+ {
+ numerator[j] += tw*diff[j];
+ }
+ denominator += tw;
+ }
+
+ for (decltype(dxdt.size()) j = 0; j < dxdt.size(); ++j)
+ {
+ dxdt[j] = numerator[j]/denominator;
+ }
+ return;
+}
+
+}}}
+#endif
diff --git a/boost/math/interpolators/detail/whittaker_shannon_detail.hpp b/boost/math/interpolators/detail/whittaker_shannon_detail.hpp
new file mode 100644
index 0000000000..3d4ace397e
--- /dev/null
+++ b/boost/math/interpolators/detail/whittaker_shannon_detail.hpp
@@ -0,0 +1,126 @@
+// Copyright Nick Thompson, 2019
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_MATH_INTERPOLATORS_WHITAKKER_SHANNON_DETAIL_HPP
+#define BOOST_MATH_INTERPOLATORS_WHITAKKER_SHANNON_DETAIL_HPP
+#include <boost/assert.hpp>
+#include <boost/math/constants/constants.hpp>
+#include <boost/math/special_functions/sin_pi.hpp>
+#include <boost/math/special_functions/cos_pi.hpp>
+
+namespace boost { namespace math { namespace interpolators { namespace detail {
+
+template<class RandomAccessContainer>
+class whittaker_shannon_detail {
+public:
+
+ using Real = typename RandomAccessContainer::value_type;
+ whittaker_shannon_detail(RandomAccessContainer&& y, Real const & t0, Real const & h) : m_y{std::move(y)}, m_t0{t0}, m_h{h}
+ {
+ for (size_t i = 1; i < m_y.size(); i += 2)
+ {
+ m_y[i] = -m_y[i];
+ }
+ }
+
+ inline Real operator()(Real t) const {
+ using boost::math::constants::pi;
+ using std::isfinite;
+ using std::floor;
+ Real y = 0;
+ Real x = (t - m_t0)/m_h;
+ Real z = x;
+ auto it = m_y.begin();
+
+ // For some reason, neither clang nor g++ will cache the address of m_y.end() in a register.
+ // Hence make a copy of it:
+ auto end = m_y.end();
+ while(it != end)
+ {
+
+ y += *it++/z;
+ z -= 1;
+ }
+
+ if (!isfinite(y))
+ {
+ BOOST_ASSERT_MSG(floor(x) == ceil(x), "Floor and ceiling should be equal.\n");
+ size_t i = static_cast<size_t>(floor(x));
+ if (i & 1)
+ {
+ return -m_y[i];
+ }
+ return m_y[i];
+ }
+ return y*boost::math::sin_pi(x)/pi<Real>();
+ }
+
+ Real prime(Real t) const {
+ using boost::math::constants::pi;
+ using std::isfinite;
+ using std::floor;
+
+ Real x = (t - m_t0)/m_h;
+ if (ceil(x) == x) {
+ Real s = 0;
+ long j = static_cast<long>(x);
+ long n = m_y.size();
+ for (long i = 0; i < n; ++i)
+ {
+ if (j - i != 0)
+ {
+ s += m_y[i]/(j-i);
+ }
+ // else derivative of sinc at zero is zero.
+ }
+ if (j & 1) {
+ s /= -m_h;
+ } else {
+ s /= m_h;
+ }
+ return s;
+ }
+ Real z = x;
+ auto it = m_y.begin();
+ Real cospix = boost::math::cos_pi(x);
+ Real sinpix_div_pi = boost::math::sin_pi(x)/pi<Real>();
+
+ Real s = 0;
+ auto end = m_y.end();
+ while(it != end)
+ {
+ s += (*it++)*(z*cospix - sinpix_div_pi)/(z*z);
+ z -= 1;
+ }
+
+ return s/m_h;
+ }
+
+
+
+ Real operator[](size_t i) const {
+ if (i & 1)
+ {
+ return -m_y[i];
+ }
+ return m_y[i];
+ }
+
+ RandomAccessContainer&& return_data() {
+ for (size_t i = 1; i < m_y.size(); i += 2)
+ {
+ m_y[i] = -m_y[i];
+ }
+ return std::move(m_y);
+ }
+
+
+private:
+ RandomAccessContainer m_y;
+ Real m_t0;
+ Real m_h;
+};
+}}}}
+#endif
diff --git a/boost/math/interpolators/vector_barycentric_rational.hpp b/boost/math/interpolators/vector_barycentric_rational.hpp
new file mode 100644
index 0000000000..8289799bc9
--- /dev/null
+++ b/boost/math/interpolators/vector_barycentric_rational.hpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright Nick Thompson, 2019
+ * 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)
+ *
+ * Exactly the same as barycentric_rational.hpp, but delivers values in $\mathbb{R}^n$.
+ * In some sense this is trivial, since each component of the vector is computed in exactly the same
+ * as would be computed by barycentric_rational.hpp. But this is a bit more efficient and convenient.
+ */
+
+#ifndef BOOST_MATH_INTERPOLATORS_VECTOR_BARYCENTRIC_RATIONAL_HPP
+#define BOOST_MATH_INTERPOLATORS_VECTOR_BARYCENTRIC_RATIONAL_HPP
+
+#include <memory>
+#include <boost/math/interpolators/detail/vector_barycentric_rational_detail.hpp>
+
+namespace boost{ namespace math{
+
+template<class TimeContainer, class SpaceContainer>
+class vector_barycentric_rational
+{
+public:
+ using Real = typename TimeContainer::value_type;
+ using Point = typename SpaceContainer::value_type;
+ vector_barycentric_rational(TimeContainer&& times, SpaceContainer&& points, size_t approximation_order = 3);
+
+ void operator()(Point& x, Real t) const;
+
+ // I have validated using google benchmark that returning a value is no more expensive populating it,
+ // at least for Eigen vectors with known size at compile-time.
+ // This is kinda a weird thing to discover since it goes against the advice of basically every high-performance computing book.
+ Point operator()(Real t) const {
+ Point p;
+ this->operator()(p, t);
+ return p;
+ }
+
+ void prime(Point& dxdt, Real t) const {
+ Point x;
+ m_imp->eval_with_prime(x, dxdt, t);
+ }
+
+ Point prime(Real t) const {
+ Point p;
+ this->prime(p, t);
+ return p;
+ }
+
+ void eval_with_prime(Point& x, Point& dxdt, Real t) const {
+ m_imp->eval_with_prime(x, dxdt, t);
+ return;
+ }
+
+ std::pair<Point, Point> eval_with_prime(Real t) const {
+ Point x;
+ Point dxdt;
+ m_imp->eval_with_prime(x, dxdt, t);
+ return {x, dxdt};
+ }
+
+private:
+ std::shared_ptr<detail::vector_barycentric_rational_imp<TimeContainer, SpaceContainer>> m_imp;
+};
+
+
+template <class TimeContainer, class SpaceContainer>
+vector_barycentric_rational<TimeContainer, SpaceContainer>::vector_barycentric_rational(TimeContainer&& times, SpaceContainer&& points, size_t approximation_order):
+ m_imp(std::make_shared<detail::vector_barycentric_rational_imp<TimeContainer, SpaceContainer>>(std::move(times), std::move(points), approximation_order))
+{
+ return;
+}
+
+template <class TimeContainer, class SpaceContainer>
+void vector_barycentric_rational<TimeContainer, SpaceContainer>::operator()(typename SpaceContainer::value_type& p, typename TimeContainer::value_type t) const
+{
+ m_imp->operator()(p, t);
+ return;
+}
+
+}}
+#endif
diff --git a/boost/math/interpolators/whittaker_shannon.hpp b/boost/math/interpolators/whittaker_shannon.hpp
new file mode 100644
index 0000000000..a5c5367a9d
--- /dev/null
+++ b/boost/math/interpolators/whittaker_shannon.hpp
@@ -0,0 +1,47 @@
+// Copyright Nick Thompson, 2019
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_MATH_INTERPOLATORS_WHITAKKER_SHANNON_HPP
+#define BOOST_MATH_INTERPOLATORS_WHITAKKER_SHANNON_HPP
+#include <memory>
+#include <boost/math/interpolators/detail/whittaker_shannon_detail.hpp>
+
+namespace boost { namespace math { namespace interpolators {
+
+template<class RandomAccessContainer>
+class whittaker_shannon {
+public:
+
+ using Real = typename RandomAccessContainer::value_type;
+ whittaker_shannon(RandomAccessContainer&& y, Real const & t0, Real const & h)
+ : m_impl(std::make_shared<detail::whittaker_shannon_detail<RandomAccessContainer>>(std::move(y), t0, h))
+ {}
+
+ inline Real operator()(Real t) const
+ {
+ return m_impl->operator()(t);
+ }
+
+ inline Real prime(Real t) const
+ {
+ return m_impl->prime(t);
+ }
+
+ inline Real operator[](size_t i) const
+ {
+ return m_impl->operator[](i);
+ }
+
+ RandomAccessContainer&& return_data()
+ {
+ return m_impl->return_data();
+ }
+
+
+private:
+ std::shared_ptr<detail::whittaker_shannon_detail<RandomAccessContainer>> m_impl;
+};
+}}}
+#endif
diff --git a/boost/math/quadrature/detail/ooura_fourier_integrals_detail.hpp b/boost/math/quadrature/detail/ooura_fourier_integrals_detail.hpp
new file mode 100644
index 0000000000..a449c29b58
--- /dev/null
+++ b/boost/math/quadrature/detail/ooura_fourier_integrals_detail.hpp
@@ -0,0 +1,651 @@
+// Copyright Nick Thompson, 2019
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_MATH_QUADRATURE_DETAIL_OOURA_FOURIER_INTEGRALS_DETAIL_HPP
+#define BOOST_MATH_QUADRATURE_DETAIL_OOURA_FOURIER_INTEGRALS_DETAIL_HPP
+#include <utility> // for std::pair.
+#include <mutex>
+#include <atomic>
+#include <vector>
+#include <iostream>
+#include <boost/math/special_functions/expm1.hpp>
+#include <boost/math/special_functions/sin_pi.hpp>
+#include <boost/math/special_functions/cos_pi.hpp>
+#include <boost/math/constants/constants.hpp>
+
+namespace boost { namespace math { namespace quadrature { namespace detail {
+
+// Ooura and Mori, A robust double exponential formula for Fourier-type integrals,
+// eta is the argument to the exponential in equation 3.3:
+template<class Real>
+std::pair<Real, Real> ooura_eta(Real x, Real alpha) {
+ using std::expm1;
+ using std::exp;
+ using std::abs;
+ Real expx = exp(x);
+ Real eta_prime = 2 + alpha/expx + expx/4;
+ Real eta;
+ // This is the fast branch:
+ if (abs(x) > 0.125) {
+ eta = 2*x - alpha*(1/expx - 1) + (expx - 1)/4;
+ }
+ else {// this is the slow branch using expm1 for small x:
+ eta = 2*x - alpha*expm1(-x) + expm1(x)/4;
+ }
+ return {eta, eta_prime};
+}
+
+// Ooura and Mori, A robust double exponential formula for Fourier-type integrals,
+// equation 3.6:
+template<class Real>
+Real calculate_ooura_alpha(Real h)
+{
+ using boost::math::constants::pi;
+ using std::log1p;
+ using std::sqrt;
+ Real x = sqrt(16 + 4*log1p(pi<Real>()/h)/h);
+ return 1/x;
+}
+
+template<class Real>
+std::pair<Real, Real> ooura_sin_node_and_weight(long n, Real h, Real alpha)
+{
+ using std::expm1;
+ using std::exp;
+ using std::abs;
+ using boost::math::constants::pi;
+ using std::isnan;
+
+ if (n == 0) {
+ // Equation 44 of https://arxiv.org/pdf/0911.4796.pdf
+ // Fourier Transform of the Stretched Exponential Function: Analytic Error Bounds,
+ // Double Exponential Transform, and Open-Source Implementation,
+ // Joachim Wuttke,
+ // The C library libkww provides functions to compute the Kohlrausch-Williams-Watts function,
+ // the Laplace-Fourier transform of the stretched (or compressed) exponential function exp(-t^beta)
+ // for exponent beta between 0.1 and 1.9 with sixteen decimal digits accuracy.
+
+ Real eta_prime_0 = Real(2) + alpha + Real(1)/Real(4);
+ Real node = pi<Real>()/(eta_prime_0*h);
+ Real weight = pi<Real>()*boost::math::sin_pi(1/(eta_prime_0*h));
+ Real eta_dbl_prime = -alpha + Real(1)/Real(4);
+ Real phi_prime_0 = (1 - eta_dbl_prime/(eta_prime_0*eta_prime_0))/2;
+ weight *= phi_prime_0;
+ return {node, weight};
+ }
+ Real x = n*h;
+ auto p = ooura_eta(x, alpha);
+ auto eta = p.first;
+ auto eta_prime = p.second;
+
+ Real expm1_meta = expm1(-eta);
+ Real exp_meta = exp(-eta);
+ Real node = -n*pi<Real>()/expm1_meta;
+
+
+ // I have verified that this is not a significant source of inaccuracy in the weight computation:
+ Real phi_prime = -(expm1_meta + x*exp_meta*eta_prime)/(expm1_meta*expm1_meta);
+
+ // The main source of inaccuracy is in computation of sin_pi.
+ // But I've agonized over this, and I think it's as good as it can get:
+ Real s = pi<Real>();
+ Real arg;
+ if(eta > 1) {
+ arg = n/( 1/exp_meta - 1 );
+ s *= boost::math::sin_pi(arg);
+ if (n&1) {
+ s *= -1;
+ }
+ }
+ else if (eta < -1) {
+ arg = n/(1-exp_meta);
+ s *= boost::math::sin_pi(arg);
+ }
+ else {
+ arg = -n*exp_meta/expm1_meta;
+ s *= boost::math::sin_pi(arg);
+ if (n&1) {
+ s *= -1;
+ }
+ }
+
+ Real weight = s*phi_prime;
+ return {node, weight};
+}
+
+#ifdef BOOST_MATH_INSTRUMENT_OOURA
+template<class Real>
+void print_ooura_estimate(size_t i, Real I0, Real I1, Real omega) {
+ using std::abs;
+ std::cout << std::defaultfloat
+ << std::setprecision(std::numeric_limits<Real>::digits10)
+ << std::fixed;
+ std::cout << "h = " << Real(1)/Real(1<<i) << ", I_h = " << I0/omega
+ << " = " << std::hexfloat << I0/omega << ", absolute error estimate = "
+ << std::defaultfloat << std::scientific << abs(I0-I1) << std::endl;
+}
+#endif
+
+
+template<class Real>
+std::pair<Real, Real> ooura_cos_node_and_weight(long n, Real h, Real alpha)
+{
+ using std::expm1;
+ using std::exp;
+ using std::abs;
+ using boost::math::constants::pi;
+
+ Real x = h*(n-Real(1)/Real(2));
+ auto p = ooura_eta(x, alpha);
+ auto eta = p.first;
+ auto eta_prime = p.second;
+ Real expm1_meta = expm1(-eta);
+ Real exp_meta = exp(-eta);
+ Real node = pi<Real>()*(Real(1)/Real(2)-n)/expm1_meta;
+
+ Real phi_prime = -(expm1_meta + x*exp_meta*eta_prime)/(expm1_meta*expm1_meta);
+
+ // Takuya Ooura and Masatake Mori,
+ // Journal of Computational and Applied Mathematics, 112 (1999) 229-241.
+ // A robust double exponential formula for Fourier-type integrals.
+ // Equation 4.6
+ Real s = pi<Real>();
+ Real arg;
+ if (eta < -1) {
+ arg = -(n-Real(1)/Real(2))/expm1_meta;
+ s *= boost::math::cos_pi(arg);
+ }
+ else {
+ arg = -(n-Real(1)/Real(2))*exp_meta/expm1_meta;
+ s *= boost::math::sin_pi(arg);
+ if (n&1) {
+ s *= -1;
+ }
+ }
+
+ Real weight = s*phi_prime;
+ return {node, weight};
+}
+
+
+template<class Real>
+class ooura_fourier_sin_detail {
+public:
+ ooura_fourier_sin_detail(const Real relative_error_goal, size_t levels) {
+#ifdef BOOST_MATH_INSTRUMENT_OOURA
+ std::cout << "ooura_fourier_sin with relative error goal " << relative_error_goal
+ << " & " << levels << " levels." << std::endl;
+#endif // BOOST_MATH_INSTRUMENT_OOURA
+ if (relative_error_goal < std::numeric_limits<Real>::epsilon() * 2) {
+ throw std::domain_error("The relative error goal cannot be smaller than the unit roundoff.");
+ }
+ using std::abs;
+ requested_levels_ = levels;
+ starting_level_ = 0;
+ rel_err_goal_ = relative_error_goal;
+ big_nodes_.reserve(levels);
+ bweights_.reserve(levels);
+ little_nodes_.reserve(levels);
+ lweights_.reserve(levels);
+
+ for (size_t i = 0; i < levels; ++i) {
+ if (std::is_same<Real, float>::value) {
+ add_level<double>(i);
+ }
+ else if (std::is_same<Real, double>::value) {
+ add_level<long double>(i);
+ }
+ else {
+ add_level<Real>(i);
+ }
+ }
+ }
+
+ std::vector<std::vector<Real>> const & big_nodes() const {
+ return big_nodes_;
+ }
+
+ std::vector<std::vector<Real>> const & weights_for_big_nodes() const {
+ return bweights_;
+ }
+
+ std::vector<std::vector<Real>> const & little_nodes() const {
+ return little_nodes_;
+ }
+
+ std::vector<std::vector<Real>> const & weights_for_little_nodes() const {
+ return lweights_;
+ }
+
+ template<class F>
+ std::pair<Real,Real> integrate(F const & f, Real omega) {
+ using std::abs;
+ using std::max;
+ using boost::math::constants::pi;
+
+ if (omega == 0) {
+ return {Real(0), Real(0)};
+ }
+ if (omega < 0) {
+ auto p = this->integrate(f, -omega);
+ return {-p.first, p.second};
+ }
+
+ Real I1 = std::numeric_limits<Real>::quiet_NaN();
+ Real relative_error_estimate = std::numeric_limits<Real>::quiet_NaN();
+ // As we compute integrals, we learn about their structure.
+ // Assuming we compute f(t)sin(wt) for many different omega, this gives some
+ // a posteriori ability to choose a refinement level that is roughly appropriate.
+ size_t i = starting_level_;
+ do {
+ Real I0 = estimate_integral(f, omega, i);
+#ifdef BOOST_MATH_INSTRUMENT_OOURA
+ print_ooura_estimate(i, I0, I1, omega);
+#endif
+ Real absolute_error_estimate = abs(I0-I1);
+ Real scale = max(abs(I0), abs(I1));
+ if (!isnan(I1) && absolute_error_estimate <= rel_err_goal_*scale) {
+ starting_level_ = max(long(i) - 1, long(0));
+ return {I0/omega, absolute_error_estimate/scale};
+ }
+ I1 = I0;
+ } while(++i < big_nodes_.size());
+
+ // We've used up all our precomputed levels.
+ // Now we need to add more.
+ // It might seems reasonable to just keep adding levels indefinitely, if that's what the user wants.
+ // But in fact the nodes and weights just merge into each other and the error gets worse after a certain number.
+ // This value for max_additional_levels was chosen by observation of a slowly converging oscillatory integral:
+ // f(x) := cos(7cos(x))sin(x)/x
+ size_t max_additional_levels = 4;
+ while (big_nodes_.size() < requested_levels_ + max_additional_levels) {
+ size_t ii = big_nodes_.size();
+ if (std::is_same<Real, float>::value) {
+ add_level<double>(ii);
+ }
+ else if (std::is_same<Real, double>::value) {
+ add_level<long double>(ii);
+ }
+ else {
+ add_level<Real>(ii);
+ }
+ Real I0 = estimate_integral(f, omega, ii);
+ Real absolute_error_estimate = abs(I0-I1);
+ Real scale = max(abs(I0), abs(I1));
+#ifdef BOOST_MATH_INSTRUMENT_OOURA
+ print_ooura_estimate(ii, I0, I1, omega);
+#endif
+ if (absolute_error_estimate <= rel_err_goal_*scale) {
+ starting_level_ = max(long(ii) - 1, long(0));
+ return {I0/omega, absolute_error_estimate/scale};
+ }
+ I1 = I0;
+ ++ii;
+ }
+
+ starting_level_ = static_cast<long>(big_nodes_.size() - 2);
+ return {I1/omega, relative_error_estimate};
+ }
+
+private:
+
+ template<class PreciseReal>
+ void add_level(size_t i) {
+ using std::abs;
+ size_t current_num_levels = big_nodes_.size();
+ Real unit_roundoff = std::numeric_limits<Real>::epsilon()/2;
+ // h0 = 1. Then all further levels have h_i = 1/2^i.
+ // Since the nodes don't nest, we could conceivably divide h by (say) 1.5, or 3.
+ // It's not clear how much benefit (or loss) would be obtained from this.
+ PreciseReal h = PreciseReal(1)/PreciseReal(1<<i);
+
+ std::vector<Real> bnode_row;
+ std::vector<Real> bweight_row;
+
+ // This is a pretty good estimate for how many elements will be placed in the vector:
+ bnode_row.reserve((static_cast<size_t>(1)<<i)*sizeof(Real));
+ bweight_row.reserve((static_cast<size_t>(1)<<i)*sizeof(Real));
+
+ std::vector<Real> lnode_row;
+ std::vector<Real> lweight_row;
+
+ lnode_row.reserve((static_cast<size_t>(1)<<i)*sizeof(Real));
+ lweight_row.reserve((static_cast<size_t>(1)<<i)*sizeof(Real));
+
+ Real max_weight = 1;
+ auto alpha = calculate_ooura_alpha(h);
+ long n = 0;
+ Real w;
+ do {
+ auto precise_nw = ooura_sin_node_and_weight(n, h, alpha);
+ Real node = static_cast<Real>(precise_nw.first);
+ Real weight = static_cast<Real>(precise_nw.second);
+ w = weight;
+ if (bnode_row.size() == bnode_row.capacity()) {
+ bnode_row.reserve(2*bnode_row.size());
+ bweight_row.reserve(2*bnode_row.size());
+ }
+
+ bnode_row.push_back(node);
+ bweight_row.push_back(weight);
+ if (abs(weight) > max_weight) {
+ max_weight = abs(weight);
+ }
+ ++n;
+ // f(t)->0 as t->infty, which is why the weights are computed up to the unit roundoff.
+ } while(abs(w) > unit_roundoff*max_weight);
+
+ // This class tends to consume a lot of memory; shrink the vectors back down to size:
+ bnode_row.shrink_to_fit();
+ bweight_row.shrink_to_fit();
+ // Why we are splitting the nodes into regimes where t_n >> 1 and t_n << 1?
+ // It will create the opportunity to sensibly truncate the quadrature sum to significant terms.
+ n = -1;
+ do {
+ auto precise_nw = ooura_sin_node_and_weight(n, h, alpha);
+ Real node = static_cast<Real>(precise_nw.first);
+ if (node <= 0) {
+ break;
+ }
+ Real weight = static_cast<Real>(precise_nw.second);
+ w = weight;
+ using std::isnan;
+ if (isnan(node)) {
+ // This occurs at n = -11 in quad precision:
+ break;
+ }
+ if (lnode_row.size() > 0) {
+ if (lnode_row[lnode_row.size()-1] == node) {
+ // The nodes have fused into each other:
+ break;
+ }
+ }
+ if (lnode_row.size() == lnode_row.capacity()) {
+ lnode_row.reserve(2*lnode_row.size());
+ lweight_row.reserve(2*lnode_row.size());
+ }
+ lnode_row.push_back(node);
+ lweight_row.push_back(weight);
+ if (abs(weight) > max_weight) {
+ max_weight = abs(weight);
+ }
+ --n;
+ // f(t)->infty is possible as t->0, hence compute up to the min.
+ } while(abs(w) > (std::numeric_limits<Real>::min)()*max_weight);
+
+ lnode_row.shrink_to_fit();
+ lweight_row.shrink_to_fit();
+
+ // std::scoped_lock once C++17 is more common?
+ std::lock_guard<std::mutex> lock(node_weight_mutex_);
+ // Another thread might have already finished this calculation and appended it to the nodes/weights:
+ if (current_num_levels == big_nodes_.size()) {
+ big_nodes_.push_back(bnode_row);
+ bweights_.push_back(bweight_row);
+
+ little_nodes_.push_back(lnode_row);
+ lweights_.push_back(lweight_row);
+ }
+ }
+
+ template<class F>
+ Real estimate_integral(F const & f, Real omega, size_t i) {
+ // Because so few function evaluations are required to get high accuracy on the integrals in the tests,
+ // Kahan summation doesn't really help.
+ //auto cond = boost::math::tools::summation_condition_number<Real, true>(0);
+ Real I0 = 0;
+ auto const & b_nodes = big_nodes_[i];
+ auto const & b_weights = bweights_[i];
+ // Will benchmark if this is helpful:
+ Real inv_omega = 1/omega;
+ for(size_t j = 0 ; j < b_nodes.size(); ++j) {
+ I0 += f(b_nodes[j]*inv_omega)*b_weights[j];
+ }
+
+ auto const & l_nodes = little_nodes_[i];
+ auto const & l_weights = lweights_[i];
+ // If f decays rapidly as |t|->infty, not all of these calls are necessary.
+ for (size_t j = 0; j < l_nodes.size(); ++j) {
+ I0 += f(l_nodes[j]*inv_omega)*l_weights[j];
+ }
+ return I0;
+ }
+
+ std::mutex node_weight_mutex_;
+ // Nodes for n >= 0, giving t_n = pi*phi(nh)/h. Generally t_n >> 1.
+ std::vector<std::vector<Real>> big_nodes_;
+ // The term bweights_ will indicate that these are weights corresponding
+ // to the big nodes:
+ std::vector<std::vector<Real>> bweights_;
+
+ // Nodes for n < 0: Generally t_n << 1, and an invariant is that t_n > 0.
+ std::vector<std::vector<Real>> little_nodes_;
+ std::vector<std::vector<Real>> lweights_;
+ Real rel_err_goal_;
+ std::atomic<long> starting_level_;
+ size_t requested_levels_;
+};
+
+template<class Real>
+class ooura_fourier_cos_detail {
+public:
+ ooura_fourier_cos_detail(const Real relative_error_goal, size_t levels) {
+#ifdef BOOST_MATH_INSTRUMENT_OOURA
+ std::cout << "ooura_fourier_cos with relative error goal " << relative_error_goal
+ << " & " << levels << " levels." << std::endl;
+ std::cout << "epsilon for type = " << std::numeric_limits<Real>::epsilon() << std::endl;
+#endif // BOOST_MATH_INSTRUMENT_OOURA
+ if (relative_error_goal < std::numeric_limits<Real>::epsilon() * 2) {
+ throw std::domain_error("The relative error goal cannot be smaller than the unit roundoff!");
+ }
+
+ using std::abs;
+ requested_levels_ = levels;
+ starting_level_ = 0;
+ rel_err_goal_ = relative_error_goal;
+ big_nodes_.reserve(levels);
+ bweights_.reserve(levels);
+ little_nodes_.reserve(levels);
+ lweights_.reserve(levels);
+
+ for (size_t i = 0; i < levels; ++i) {
+ if (std::is_same<Real, float>::value) {
+ add_level<double>(i);
+ }
+ else if (std::is_same<Real, double>::value) {
+ add_level<long double>(i);
+ }
+ else {
+ add_level<Real>(i);
+ }
+ }
+
+ }
+
+ template<class F>
+ std::pair<Real,Real> integrate(F const & f, Real omega) {
+ using std::abs;
+ using std::max;
+ using boost::math::constants::pi;
+
+ if (omega == 0) {
+ throw std::domain_error("At omega = 0, the integral is not oscillatory. The user must choose an appropriate method for this case.\n");
+ }
+
+ if (omega < 0) {
+ return this->integrate(f, -omega);
+ }
+
+ Real I1 = std::numeric_limits<Real>::quiet_NaN();
+ Real absolute_error_estimate = std::numeric_limits<Real>::quiet_NaN();
+ Real scale = std::numeric_limits<Real>::quiet_NaN();
+ size_t i = starting_level_;
+ do {
+ Real I0 = estimate_integral(f, omega, i);
+#ifdef BOOST_MATH_INSTRUMENT_OOURA
+ print_ooura_estimate(i, I0, I1, omega);
+#endif
+ absolute_error_estimate = abs(I0-I1);
+ scale = max(abs(I0), abs(I1));
+ if (!isnan(I1) && absolute_error_estimate <= rel_err_goal_*scale) {
+ starting_level_ = max(long(i) - 1, long(0));
+ return {I0/omega, absolute_error_estimate/scale};
+ }
+ I1 = I0;
+ } while(++i < big_nodes_.size());
+
+ size_t max_additional_levels = 4;
+ while (big_nodes_.size() < requested_levels_ + max_additional_levels) {
+ size_t ii = big_nodes_.size();
+ if (std::is_same<Real, float>::value) {
+ add_level<double>(ii);
+ }
+ else if (std::is_same<Real, double>::value) {
+ add_level<long double>(ii);
+ }
+ else {
+ add_level<Real>(ii);
+ }
+ Real I0 = estimate_integral(f, omega, ii);
+#ifdef BOOST_MATH_INSTRUMENT_OOURA
+ print_ooura_estimate(ii, I0, I1, omega);
+#endif
+ absolute_error_estimate = abs(I0-I1);
+ scale = max(abs(I0), abs(I1));
+ if (absolute_error_estimate <= rel_err_goal_*scale) {
+ starting_level_ = max(long(ii) - 1, long(0));
+ return {I0/omega, absolute_error_estimate/scale};
+ }
+ I1 = I0;
+ ++ii;
+ }
+
+ starting_level_ = static_cast<long>(big_nodes_.size() - 2);
+ return {I1/omega, absolute_error_estimate/scale};
+ }
+
+private:
+
+ template<class PreciseReal>
+ void add_level(size_t i) {
+ using std::abs;
+ size_t current_num_levels = big_nodes_.size();
+ Real unit_roundoff = std::numeric_limits<Real>::epsilon()/2;
+ PreciseReal h = PreciseReal(1)/PreciseReal(1<<i);
+
+ std::vector<Real> bnode_row;
+ std::vector<Real> bweight_row;
+ bnode_row.reserve((static_cast<size_t>(1)<<i)*sizeof(Real));
+ bweight_row.reserve((static_cast<size_t>(1)<<i)*sizeof(Real));
+
+ std::vector<Real> lnode_row;
+ std::vector<Real> lweight_row;
+
+ lnode_row.reserve((static_cast<size_t>(1)<<i)*sizeof(Real));
+ lweight_row.reserve((static_cast<size_t>(1)<<i)*sizeof(Real));
+
+ Real max_weight = 1;
+ auto alpha = calculate_ooura_alpha(h);
+ long n = 0;
+ Real w;
+ do {
+ auto precise_nw = ooura_cos_node_and_weight(n, h, alpha);
+ Real node = static_cast<Real>(precise_nw.first);
+ Real weight = static_cast<Real>(precise_nw.second);
+ w = weight;
+ if (bnode_row.size() == bnode_row.capacity()) {
+ bnode_row.reserve(2*bnode_row.size());
+ bweight_row.reserve(2*bnode_row.size());
+ }
+
+ bnode_row.push_back(node);
+ bweight_row.push_back(weight);
+ if (abs(weight) > max_weight) {
+ max_weight = abs(weight);
+ }
+ ++n;
+ // f(t)->0 as t->infty, which is why the weights are computed up to the unit roundoff.
+ } while(abs(w) > unit_roundoff*max_weight);
+
+ bnode_row.shrink_to_fit();
+ bweight_row.shrink_to_fit();
+ n = -1;
+ do {
+ auto precise_nw = ooura_cos_node_and_weight(n, h, alpha);
+ Real node = static_cast<Real>(precise_nw.first);
+ // The function cannot be singular at zero,
+ // so zero is not a unreasonable node,
+ // unlike in the case of the Fourier Sine.
+ // Hence only break if the node is negative.
+ if (node < 0) {
+ break;
+ }
+ Real weight = static_cast<Real>(precise_nw.second);
+ w = weight;
+ if (lnode_row.size() > 0) {
+ if (lnode_row.back() == node) {
+ // The nodes have fused into each other:
+ break;
+ }
+ }
+ if (lnode_row.size() == lnode_row.capacity()) {
+ lnode_row.reserve(2*lnode_row.size());
+ lweight_row.reserve(2*lnode_row.size());
+ }
+
+ lnode_row.push_back(node);
+ lweight_row.push_back(weight);
+ if (abs(weight) > max_weight) {
+ max_weight = abs(weight);
+ }
+ --n;
+ } while(abs(w) > (std::numeric_limits<Real>::min)()*max_weight);
+
+ lnode_row.shrink_to_fit();
+ lweight_row.shrink_to_fit();
+
+ std::lock_guard<std::mutex> lock(node_weight_mutex_);
+ // Another thread might have already finished this calculation and appended it to the nodes/weights:
+ if (current_num_levels == big_nodes_.size()) {
+ big_nodes_.push_back(bnode_row);
+ bweights_.push_back(bweight_row);
+
+ little_nodes_.push_back(lnode_row);
+ lweights_.push_back(lweight_row);
+ }
+ }
+
+ template<class F>
+ Real estimate_integral(F const & f, Real omega, size_t i) {
+ Real I0 = 0;
+ auto const & b_nodes = big_nodes_[i];
+ auto const & b_weights = bweights_[i];
+ Real inv_omega = 1/omega;
+ for(size_t j = 0 ; j < b_nodes.size(); ++j) {
+ I0 += f(b_nodes[j]*inv_omega)*b_weights[j];
+ }
+
+ auto const & l_nodes = little_nodes_[i];
+ auto const & l_weights = lweights_[i];
+ for (size_t j = 0; j < l_nodes.size(); ++j) {
+ I0 += f(l_nodes[j]*inv_omega)*l_weights[j];
+ }
+ return I0;
+ }
+
+ std::mutex node_weight_mutex_;
+ std::vector<std::vector<Real>> big_nodes_;
+ std::vector<std::vector<Real>> bweights_;
+
+ std::vector<std::vector<Real>> little_nodes_;
+ std::vector<std::vector<Real>> lweights_;
+ Real rel_err_goal_;
+ std::atomic<long> starting_level_;
+ size_t requested_levels_;
+};
+
+
+}}}}
+#endif
diff --git a/boost/math/quadrature/ooura_fourier_integrals.hpp b/boost/math/quadrature/ooura_fourier_integrals.hpp
new file mode 100644
index 0000000000..b31996c2bc
--- /dev/null
+++ b/boost/math/quadrature/ooura_fourier_integrals.hpp
@@ -0,0 +1,68 @@
+// Copyright Nick Thompson, 2019
+// 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)
+
+/*
+ * References:
+ * Ooura, Takuya, and Masatake Mori. "A robust double exponential formula for Fourier-type integrals." Journal of computational and applied mathematics 112.1-2 (1999): 229-241.
+ * http://www.kurims.kyoto-u.ac.jp/~ooura/intde.html
+ */
+#ifndef BOOST_MATH_QUADRATURE_OOURA_FOURIER_INTEGRALS_HPP
+#define BOOST_MATH_QUADRATURE_OOURA_FOURIER_INTEGRALS_HPP
+#include <memory>
+#include <boost/math/quadrature/detail/ooura_fourier_integrals_detail.hpp>
+
+namespace boost { namespace math { namespace quadrature {
+
+template<class Real>
+class ooura_fourier_sin {
+public:
+ ooura_fourier_sin(const Real relative_error_tolerance = tools::root_epsilon<Real>(), size_t levels = sizeof(Real)) : impl_(std::make_shared<detail::ooura_fourier_sin_detail<Real>>(relative_error_tolerance, levels))
+ {}
+
+ template<class F>
+ std::pair<Real, Real> integrate(F const & f, Real omega) {
+ return impl_->integrate(f, omega);
+ }
+
+ // These are just for debugging/unit tests:
+ std::vector<std::vector<Real>> const & big_nodes() const {
+ return impl_->big_nodes();
+ }
+
+ std::vector<std::vector<Real>> const & weights_for_big_nodes() const {
+ return impl_->weights_for_big_nodes();
+ }
+
+ std::vector<std::vector<Real>> const & little_nodes() const {
+ return impl_->little_nodes();
+ }
+
+ std::vector<std::vector<Real>> const & weights_for_little_nodes() const {
+ return impl_->weights_for_little_nodes();
+ }
+
+private:
+ std::shared_ptr<detail::ooura_fourier_sin_detail<Real>> impl_;
+};
+
+
+template<class Real>
+class ooura_fourier_cos {
+public:
+ ooura_fourier_cos(const Real relative_error_tolerance = tools::root_epsilon<Real>(), size_t levels = sizeof(Real)) : impl_(std::make_shared<detail::ooura_fourier_cos_detail<Real>>(relative_error_tolerance, levels))
+ {}
+
+ template<class F>
+ std::pair<Real, Real> integrate(F const & f, Real omega) {
+ return impl_->integrate(f, omega);
+ }
+private:
+ std::shared_ptr<detail::ooura_fourier_cos_detail<Real>> impl_;
+};
+
+
+}}}
+#endif
diff --git a/boost/math/special_functions/beta.hpp b/boost/math/special_functions/beta.hpp
index 35b114ef15..c4acbcb4b0 100644
--- a/boost/math/special_functions/beta.hpp
+++ b/boost/math/special_functions/beta.hpp
@@ -790,8 +790,11 @@ struct Pn_size
{
// This is likely to be enough for ~35-50 digit accuracy
// but it's hard to quantify exactly:
- BOOST_STATIC_CONSTANT(unsigned, value = 50);
- BOOST_STATIC_ASSERT(::boost::math::max_factorial<T>::value >= 100);
+ BOOST_STATIC_CONSTANT(unsigned, value =
+ ::boost::math::max_factorial<T>::value >= 100 ? 50
+ : ::boost::math::max_factorial<T>::value >= ::boost::math::max_factorial<double>::value ? 30
+ : ::boost::math::max_factorial<T>::value >= ::boost::math::max_factorial<float>::value ? 15 : 1);
+ BOOST_STATIC_ASSERT(::boost::math::max_factorial<T>::value >= ::boost::math::max_factorial<float>::value);
};
template <>
struct Pn_size<float>
diff --git a/boost/math/special_functions/cos_pi.hpp b/boost/math/special_functions/cos_pi.hpp
index 669a2c87ae..f9aeeca993 100644
--- a/boost/math/special_functions/cos_pi.hpp
+++ b/boost/math/special_functions/cos_pi.hpp
@@ -33,7 +33,7 @@ T cos_pi_imp(T x, const Policy& pol)
x = -x;
}
T rem = floor(x);
- if(itrunc(rem, pol) & 1)
+ if(iconvert(rem, pol) & 1)
invert = !invert;
rem = x - rem;
if(rem > 0.5f)
@@ -66,7 +66,10 @@ inline typename tools::promote_args<T>::type cos_pi(T x, const Policy&)
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
+ policies::assert_undefined<>,
+ // We want to igore overflows since the result is in [-1,1] and the
+ // check slows the code down considerably.
+ policies::overflow_error<policies::ignore_error> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, forwarding_policy>(boost::math::detail::cos_pi_imp<value_type>(x, forwarding_policy()), "cos_pi");
}
diff --git a/boost/math/special_functions/detail/unchecked_factorial.hpp b/boost/math/special_functions/detail/unchecked_factorial.hpp
index 642df7ce50..aa5b484df0 100644
--- a/boost/math/special_functions/detail/unchecked_factorial.hpp
+++ b/boost/math/special_functions/detail/unchecked_factorial.hpp
@@ -775,18 +775,58 @@ inline T unchecked_factorial_imp(unsigned i, const mpl::int_<0>&)
}
template <class T>
+inline T unchecked_factorial_imp(unsigned i, const mpl::int_<std::numeric_limits<float>::digits>&)
+{
+ return unchecked_factorial<float>(i);
+}
+
+template <class T>
+inline T unchecked_factorial_imp(unsigned i, const mpl::int_<std::numeric_limits<double>::digits>&)
+{
+ return unchecked_factorial<double>(i);
+}
+
+#if DBL_MANT_DIG != LDBL_MANT_DIG
+template <class T>
+inline T unchecked_factorial_imp(unsigned i, const mpl::int_<LDBL_MANT_DIG>&)
+{
+ return unchecked_factorial<long double>(i);
+}
+#endif
+#ifdef BOOST_MATH_USE_FLOAT128
+template <class T>
+inline T unchecked_factorial_imp(unsigned i, const mpl::int_<113>&)
+{
+ return unchecked_factorial<BOOST_MATH_FLOAT128_TYPE>(i);
+}
+#endif
+
+template <class T>
inline T unchecked_factorial(unsigned i)
{
typedef typename boost::math::policies::precision<T, boost::math::policies::policy<> >::type tag_type;
return unchecked_factorial_imp<T>(i, tag_type());
}
+#ifdef BOOST_MATH_USE_FLOAT128
+#define BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL : std::numeric_limits<T>::digits == 113 ? max_factorial<BOOST_MATH_FLOAT128_TYPE>::value
+#else
+#define BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL
+#endif
+
template <class T>
struct max_factorial
{
- BOOST_STATIC_CONSTANT(unsigned, value = 100);
+ BOOST_STATIC_CONSTANT(unsigned, value =
+ std::numeric_limits<T>::digits == std::numeric_limits<float>::digits ? max_factorial<float>::value
+ : std::numeric_limits<T>::digits == std::numeric_limits<double>::digits ? max_factorial<double>::value
+ : std::numeric_limits<T>::digits == std::numeric_limits<long double>::digits ? max_factorial<long double>::value
+ BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL
+ : 100);
};
+#undef BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL
+
#else // BOOST_MATH_NO_LEXICAL_CAST
template <class T>
diff --git a/boost/math/special_functions/ellint_1.hpp b/boost/math/special_functions/ellint_1.hpp
index d1d9d72e30..334c0ad808 100644
--- a/boost/math/special_functions/ellint_1.hpp
+++ b/boost/math/special_functions/ellint_1.hpp
@@ -51,12 +51,6 @@ T ellint_f_imp(T phi, T k, const Policy& pol)
BOOST_MATH_INSTRUMENT_VARIABLE(k);
BOOST_MATH_INSTRUMENT_VARIABLE(function);
- if (abs(k) > 1)
- {
- return policies::raise_domain_error<T>(function,
- "Got k = %1%, function requires |k| <= 1", k, pol);
- }
-
bool invert = false;
if(phi < 0)
{
@@ -104,18 +98,24 @@ T ellint_f_imp(T phi, T k, const Policy& pol)
}
T sinp = sin(rphi);
sinp *= sinp;
+ if (sinp * k * k >= 1)
+ {
+ return policies::raise_domain_error<T>(function,
+ "Got k^2 * sin^2(phi) = %1%, but the function requires this < 1", sinp * k * k, pol);
+ }
T cosp = cos(rphi);
cosp *= cosp;
BOOST_MATH_INSTRUMENT_VARIABLE(sinp);
BOOST_MATH_INSTRUMENT_VARIABLE(cosp);
if(sinp > tools::min_value<T>())
{
+ BOOST_ASSERT(rphi != 0); // precondition, can't be true if sin(rphi) != 0.
//
// Use http://dlmf.nist.gov/19.25#E5, note that
// c-1 simplifies to cot^2(rphi) which avoid cancellation:
//
T c = 1 / sinp;
- result = rphi == 0 ? static_cast<T>(0) : static_cast<T>(s * ellint_rf_imp(T(cosp / sinp), T(c - k * k), c, pol));
+ result = static_cast<T>(s * ellint_rf_imp(T(cosp / sinp), T(c - k * k), c, pol));
}
else
result = s * sin(rphi);
diff --git a/boost/math/special_functions/ellint_2.hpp b/boost/math/special_functions/ellint_2.hpp
index 9ee6b63821..2687e9c8ce 100644
--- a/boost/math/special_functions/ellint_2.hpp
+++ b/boost/math/special_functions/ellint_2.hpp
@@ -49,6 +49,9 @@ T ellint_e_imp(T phi, T k, const Policy& pol)
using namespace boost::math::constants;
bool invert = false;
+ if (phi == 0)
+ return 0;
+
if(phi < 0)
{
phi = fabs(phi);
@@ -95,11 +98,7 @@ T ellint_e_imp(T phi, T k, const Policy& pol)
rphi = constants::half_pi<T>() - rphi;
}
T k2 = k * k;
- if(k2 > 1)
- {
- return policies::raise_domain_error<T>("boost::math::ellint_2<%1%>(%1%, %1%)", "The parameter k is out of range, got k = %1%", k, pol);
- }
- else if(rphi < tools::root_epsilon<T>())
+ if(boost::math::pow<3>(rphi) * k2 / 6 < tools::epsilon<T>() * fabs(rphi))
{
// See http://functions.wolfram.com/EllipticIntegrals/EllipticE2/06/01/03/0001/
result = s * rphi;
@@ -108,6 +107,10 @@ T ellint_e_imp(T phi, T k, const Policy& pol)
{
// http://dlmf.nist.gov/19.25#E10
T sinp = sin(rphi);
+ if (k2 * sinp * sinp >= 1)
+ {
+ return policies::raise_domain_error<T>("boost::math::ellint_2<%1%>(%1%, %1%)", "The parameter k is out of range, got k = %1%", k, pol);
+ }
T cosp = cos(rphi);
T c = 1 / (sinp * sinp);
T cm1 = cosp * cosp / (sinp * sinp); // c - 1
diff --git a/boost/math/special_functions/ellint_3.hpp b/boost/math/special_functions/ellint_3.hpp
index b8b36729cf..dfc104514e 100644
--- a/boost/math/special_functions/ellint_3.hpp
+++ b/boost/math/special_functions/ellint_3.hpp
@@ -49,15 +49,15 @@ T ellint_pi_imp(T v, T phi, T k, T vc, const Policy& pol)
static const char* function = "boost::math::ellint_3<%1%>(%1%,%1%,%1%)";
- if(abs(k) > 1)
- {
- return policies::raise_domain_error<T>(function,
- "Got k = %1%, function requires |k| <= 1", k, pol);
- }
T sphi = sin(fabs(phi));
T result = 0;
+ if (k * k * sphi * sphi > 1)
+ {
+ return policies::raise_domain_error<T>(function,
+ "Got k = %1%, function requires |k| <= 1", k, pol);
+ }
// Special cases first:
if(v == 0)
{
@@ -73,6 +73,9 @@ T ellint_pi_imp(T v, T phi, T k, T vc, const Policy& pol)
if(v == 1)
{
+ if (k == 0)
+ return tan(phi);
+
// http://functions.wolfram.com/08.06.03.0008.01
T m = k * k;
result = sqrt(1 - m * sphi * sphi) * tan(phi) - ellint_e_imp(phi, k, pol);
@@ -143,10 +146,6 @@ T ellint_pi_imp(T v, T phi, T k, T vc, const Policy& pol)
T vcr = sqrt(vc);
return atan(vcr * tan(phi)) / vcr;
}
- else if(v == 1)
- {
- return tan(phi);
- }
else
{
// v > 1:
@@ -155,7 +154,7 @@ T ellint_pi_imp(T v, T phi, T k, T vc, const Policy& pol)
return (boost::math::log1p(arg, pol) - boost::math::log1p(-arg, pol)) / (2 * vcr);
}
}
- if(v < 0)
+ if((v < 0) && fabs(k) <= 1)
{
//
// If we don't shift to 0 <= v <= 1 we get
diff --git a/boost/math/special_functions/ellint_d.hpp b/boost/math/special_functions/ellint_d.hpp
index fa5c53db18..b482922d5d 100644
--- a/boost/math/special_functions/ellint_d.hpp
+++ b/boost/math/special_functions/ellint_d.hpp
@@ -91,7 +91,7 @@ T ellint_d_imp(T phi, T k, const Policy& pol)
T c = 1 / (sinp * sinp);
T cm1 = cosp * cosp / (sinp * sinp); // c - 1
T k2 = k * k;
- if(k2 > 1)
+ if(k2 * sinp * sinp > 1)
{
return policies::raise_domain_error<T>("boost::math::ellint_d<%1%>(%1%, %1%)", "The parameter k is out of range, got k = %1%", k, pol);
}
diff --git a/boost/math/special_functions/lambert_w.hpp b/boost/math/special_functions/lambert_w.hpp
index 6b3dcebe2f..65d3be5f5c 100644
--- a/boost/math/special_functions/lambert_w.hpp
+++ b/boost/math/special_functions/lambert_w.hpp
@@ -61,7 +61,7 @@ BOOST_MATH_INSTRUMENT_LAMBERT_W_SMALL_Z_SERIES_ITERATIONS // Show evaluation of
#include <boost/mpl/int.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/math/tools/precision.hpp> // boost::math::tools::max_value().
-#include <boost/math/tools/test_value.hpp> // For create_test_value and macro BOOST_MATH_TEST_VALUE.
+#include <boost/math/tools/big_constant.hpp>
#include <limits>
#include <cmath>
@@ -296,27 +296,27 @@ T lambert_w_singularity_series(const T p)
// -T(0.000672061631156136204L), j14
//+T(1003663334225097487uLL) / 234281684403486720000uLL, // j15 0.00044247306181462090993020760858473726479232802068800 error C2177: constant too big
//+T(0.000442473061814620910L, // j15
- BOOST_MATH_TEST_VALUE(T, +0.000442473061814620910), // j15
+ BOOST_MATH_BIG_CONSTANT(T, 64, +0.000442473061814620910), // j15
// -T(0.000292677224729627445L), // j16
- BOOST_MATH_TEST_VALUE(T, -0.000292677224729627445), // j16
+ BOOST_MATH_BIG_CONSTANT(T, 64, -0.000292677224729627445), // j16
//+T(0.000194387276054539318L), // j17
- BOOST_MATH_TEST_VALUE(T, 0.000194387276054539318), // j17
+ BOOST_MATH_BIG_CONSTANT(T, 64, 0.000194387276054539318), // j17
//-T(0.000129574266852748819L), // j18
- BOOST_MATH_TEST_VALUE(T, -0.000129574266852748819), // j18
+ BOOST_MATH_BIG_CONSTANT(T, 64, -0.000129574266852748819), // j18
//+T(0.0000866503580520812717L), // j19 N[+1150497127780071399782389/13277465363600276402995200000, 50] 0.000086650358052081271660451590462390293190597827783288
- BOOST_MATH_TEST_VALUE(T, +0.0000866503580520812717), // j19
+ BOOST_MATH_BIG_CONSTANT(T, 64, +0.0000866503580520812717), // j19
//-T(0.0000581136075044138168L) // j20 N[2853534237182741069/49102686267859224000000, 50] 0.000058113607504413816772205464778828177256611844221913
// -T(2853534237182741069uLL) / 49102686267859224000000uLL // j20 // error C2177: constant too big,
- // so must use BOOST_MATH_TEST_VALUE(T, ) format in hope of using suffix Q for quad or decimal digits string for others.
+ // so must use BOOST_MATH_BIG_CONSTANT(T, ) format in hope of using suffix Q for quad or decimal digits string for others.
//-T(0.000058113607504413816772205464778828177256611844221913L), // j20 N[2853534237182741069/49102686267859224000000, 50] 0.000058113607504413816772205464778828177256611844221913
- BOOST_MATH_TEST_VALUE(T, -0.000058113607504413816772205464778828177256611844221913) // j20 - last used by Fukushima
+ BOOST_MATH_BIG_CONSTANT(T, 113, -0.000058113607504413816772205464778828177256611844221913) // j20 - last used by Fukushima
// More terms don't seem to give any improvement (worse in fact) and are not use for many z values.
- //BOOST_MATH_TEST_VALUE(T, +0.000039076684867439051635395583044527492132109160553593), // j21
- //BOOST_MATH_TEST_VALUE(T, -0.000026338064747231098738584082718649443078703982217219), // j22
- //BOOST_MATH_TEST_VALUE(T, +0.000017790345805079585400736282075184540383274460464169), // j23
- //BOOST_MATH_TEST_VALUE(T, -0.000012040352739559976942274116578992585158113153190354), // j24
- //BOOST_MATH_TEST_VALUE(T, +8.1635319824966121713827512573558687050675701559448E-6), // j25
- //BOOST_MATH_TEST_VALUE(T, -5.5442032085673591366657251660804575198155559225316E-6) // j26
+ //BOOST_MATH_BIG_CONSTANT(T, +0.000039076684867439051635395583044527492132109160553593), // j21
+ //BOOST_MATH_BIG_CONSTANT(T, -0.000026338064747231098738584082718649443078703982217219), // j22
+ //BOOST_MATH_BIG_CONSTANT(T, +0.000017790345805079585400736282075184540383274460464169), // j23
+ //BOOST_MATH_BIG_CONSTANT(T, -0.000012040352739559976942274116578992585158113153190354), // j24
+ //BOOST_MATH_BIG_CONSTANT(T, +8.1635319824966121713827512573558687050675701559448E-6), // j25
+ //BOOST_MATH_BIG_CONSTANT(T, -5.5442032085673591366657251660804575198155559225316E-6) // j26
// -T(5.5442032085673591366657251660804575198155559225316E-6L) // j26
// 21 to 26 Added for long double.
}; // static const T q[]
diff --git a/boost/math/special_functions/prime.hpp b/boost/math/special_functions/prime.hpp
index 858d96d10b..31a9cba868 100644
--- a/boost/math/special_functions/prime.hpp
+++ b/boost/math/special_functions/prime.hpp
@@ -1232,7 +1232,7 @@ namespace boost{ namespace math{
return boost::math::prime(n, boost::math::policies::policy<>());
}
- static const unsigned max_prime = 10000;
+ static const unsigned max_prime = 9999;
}} // namespace boost and math
diff --git a/boost/math/special_functions/sin_pi.hpp b/boost/math/special_functions/sin_pi.hpp
index ae6b3e7442..de80387320 100644
--- a/boost/math/special_functions/sin_pi.hpp
+++ b/boost/math/special_functions/sin_pi.hpp
@@ -20,11 +20,11 @@
namespace boost{ namespace math{ namespace detail{
template <class T, class Policy>
-T sin_pi_imp(T x, const Policy& pol)
+inline T sin_pi_imp(T x, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std names
if(x < 0)
- return -sin_pi(-x);
+ return -sin_pi_imp(T(-x), pol);
// sin of pi*x:
bool invert;
if(x < 0.5)
@@ -38,7 +38,7 @@ T sin_pi_imp(T x, const Policy& pol)
invert = false;
T rem = floor(x);
- if(itrunc(rem, pol) & 1)
+ if(iconvert(rem, pol) & 1)
invert = !invert;
rem = x - rem;
if(rem > 0.5f)
@@ -62,8 +62,11 @@ inline typename tools::promote_args<T>::type sin_pi(T x, const Policy&)
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- return policies::checked_narrowing_cast<result_type, forwarding_policy>(boost::math::detail::sin_pi_imp<value_type>(x, forwarding_policy()), "cos_pi");
+ policies::assert_undefined<>,
+ // We want to igore overflows since the result is in [-1,1] and the
+ // check slows the code down considerably.
+ policies::overflow_error<policies::ignore_error> >::type forwarding_policy;
+ return policies::checked_narrowing_cast<result_type, forwarding_policy>(boost::math::detail::sin_pi_imp<value_type>(x, forwarding_policy()), "sin_pi");
}
template <class T>
diff --git a/boost/math/special_functions/trunc.hpp b/boost/math/special_functions/trunc.hpp
index 8a7b042449..2671a0dc88 100644
--- a/boost/math/special_functions/trunc.hpp
+++ b/boost/math/special_functions/trunc.hpp
@@ -14,6 +14,8 @@
#include <boost/math/tools/config.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
+#include <boost/type_traits/is_constructible.hpp>
+#include <boost/core/enable_if.hpp>
namespace boost{ namespace math{ namespace detail{
@@ -106,6 +108,55 @@ inline boost::long_long_type lltrunc(const T& v)
#endif
+template <class T, class Policy>
+inline typename boost::enable_if_c<boost::is_constructible<int, T>::value, int>::type
+ iconvert(const T& v, const Policy&)
+{
+ return static_cast<int>(v);
+}
+
+template <class T, class Policy>
+inline typename boost::disable_if_c<boost::is_constructible<int, T>::value, int>::type
+ iconvert(const T& v, const Policy& pol)
+{
+ using boost::math::itrunc;
+ return itrunc(v, pol);
+}
+
+template <class T, class Policy>
+inline typename boost::enable_if_c<boost::is_constructible<long, T>::value, long>::type
+ lconvert(const T& v, const Policy&)
+{
+ return static_cast<long>(v);
+}
+
+template <class T, class Policy>
+inline typename boost::disable_if_c<boost::is_constructible<long, T>::value, long>::type
+ lconvert(const T& v, const Policy& pol)
+{
+ using boost::math::ltrunc;
+ return ltrunc(v, pol);
+}
+
+#ifdef BOOST_HAS_LONG_LONG
+
+template <class T, class Policy>
+inline typename boost::enable_if_c<boost::is_constructible<boost::long_long_type, T>::value, boost::long_long_type>::type
+ llconvertert(const T& v, const Policy&)
+{
+ return static_cast<boost::long_long_type>(v);
+}
+
+template <class T, class Policy>
+inline typename boost::disable_if_c<boost::is_constructible<boost::long_long_type, T>::value, boost::long_long_type>::type
+ llconvertert(const T& v, const Policy& pol)
+{
+ using boost::math::lltrunc;
+ return lltrunc(v, pol);
+}
+
+#endif
+
}} // namespaces
#endif // BOOST_MATH_TRUNC_HPP
diff --git a/boost/math/tools/roots.hpp b/boost/math/tools/roots.hpp
index e16294dc15..552f7f7ae3 100644
--- a/boost/math/tools/roots.hpp
+++ b/boost/math/tools/roots.hpp
@@ -32,6 +32,7 @@
#endif
#include <boost/math/special_functions/sign.hpp>
+#include <boost/math/special_functions/next.hpp>
#include <boost/math/tools/toms748_solve.hpp>
#include <boost/math/policies/error_handling.hpp>
@@ -245,6 +246,11 @@ T newton_raphson_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_
boost::uintmax_t count(max_iter);
+#ifdef BOOST_MATH_INSTRUMENT
+ std::cout << "Newton_raphson_iterate, guess = " << guess << ", min = " << min << ", max = " << max
+ << ", digits = " << digits << ", max_iter = " << max_iter << std::endl;
+#endif
+
do{
last_f0 = f0;
delta2 = delta1;
@@ -257,7 +263,7 @@ T newton_raphson_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_
{
// Oops zero derivative!!!
#ifdef BOOST_MATH_INSTRUMENT
- std::cout << "Newton iteration, zero derivative found" << std::endl;
+ std::cout << "Newton iteration, zero derivative found!" << std::endl;
#endif
detail::handle_zero_derivative(f, last_f0, f0, delta, result, guess, min, max);
}
@@ -266,15 +272,16 @@ T newton_raphson_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_
delta = f0 / f1;
}
#ifdef BOOST_MATH_INSTRUMENT
- std::cout << "Newton iteration, delta = " << delta << std::endl;
+ std::cout << "Newton iteration " << max_iter - count << ", delta = " << delta << std::endl;
#endif
if(fabs(delta * 2) > fabs(delta2))
{
- // last two steps haven't converged.
+ // Last two steps haven't converged.
T shift = (delta > 0) ? (result - min) / 2 : (result - max) / 2;
if ((result != 0) && (fabs(shift) > fabs(result)))
{
- delta = sign(delta) * result; // protect against huge jumps!
+ delta = sign(delta) * fabs(result) * 0.9; // Protect against huge jumps!
+ //delta = sign(delta) * result; // Protect against huge jumps! Failed for negative result. https://github.com/boostorg/math/issues/216
}
else
delta = shift;
@@ -298,7 +305,7 @@ T newton_raphson_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_
if((result == min) || (result == max))
break;
}
- // update brackets:
+ // Update brackets:
if(delta > 0)
max = guess;
else
@@ -308,13 +315,14 @@ T newton_raphson_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_
max_iter -= count;
#ifdef BOOST_MATH_INSTRUMENT
- std::cout << "Newton Raphson iteration, final count = " << max_iter << std::endl;
+ std::cout << "Newton Raphson final iteration count = " << max_iter << std::endl;
static boost::uintmax_t max_count = 0;
if(max_iter > max_count)
{
max_count = max_iter;
- std::cout << "Maximum iterations: " << max_iter << std::endl;
+ // std::cout << "Maximum iterations: " << max_iter << std::endl;
+ // Puzzled what this tells us, so commented out for now?
}
#endif
@@ -354,12 +362,131 @@ namespace detail{
}
};
+ template <class F, class T>
+ T bracket_root_towards_min(F f, T guess, const T& f0, T& min, T& max, boost::uintmax_t& count);
+
+ template <class F, class T>
+ T bracket_root_towards_max(F f, T guess, const T& f0, T& min, T& max, boost::uintmax_t& count)
+ {
+ using std::fabs;
+ //
+ // Move guess towards max until we bracket the root, updating min and max as we go:
+ //
+ T guess0 = guess;
+ T multiplier = 2;
+ T f_current = f0;
+ if (fabs(min) < fabs(max))
+ {
+ while (--count && ((f_current < 0) == (f0 < 0)))
+ {
+ min = guess;
+ guess *= multiplier;
+ if (guess > max)
+ {
+ guess = max;
+ f_current = -f_current; // There must be a change of sign!
+ break;
+ }
+ multiplier *= 2;
+ unpack_0(f(guess), f_current);
+ }
+ }
+ else
+ {
+ //
+ // If min and max are negative we have to divide to head towards max:
+ //
+ while (--count && ((f_current < 0) == (f0 < 0)))
+ {
+ min = guess;
+ guess /= multiplier;
+ if (guess > max)
+ {
+ guess = max;
+ f_current = -f_current; // There must be a change of sign!
+ break;
+ }
+ multiplier *= 2;
+ unpack_0(f(guess), f_current);
+ }
+ }
+
+ if (count)
+ {
+ max = guess;
+ if (multiplier > 16)
+ return (guess0 - guess) + bracket_root_towards_min(f, guess, f_current, min, max, count);
+ }
+ return guess0 - (max + min) / 2;
+ }
+
+ template <class F, class T>
+ T bracket_root_towards_min(F f, T guess, const T& f0, T& min, T& max, boost::uintmax_t& count)
+ {
+ using std::fabs;
+ //
+ // Move guess towards min until we bracket the root, updating min and max as we go:
+ //
+ T guess0 = guess;
+ T multiplier = 2;
+ T f_current = f0;
+
+ if (fabs(min) < fabs(max))
+ {
+ while (--count && ((f_current < 0) == (f0 < 0)))
+ {
+ max = guess;
+ guess /= multiplier;
+ if (guess < min)
+ {
+ guess = min;
+ f_current = -f_current; // There must be a change of sign!
+ break;
+ }
+ multiplier *= 2;
+ unpack_0(f(guess), f_current);
+ }
+ }
+ else
+ {
+ //
+ // If min and max are negative we have to multiply to head towards min:
+ //
+ while (--count && ((f_current < 0) == (f0 < 0)))
+ {
+ max = guess;
+ guess *= multiplier;
+ if (guess < min)
+ {
+ guess = min;
+ f_current = -f_current; // There must be a change of sign!
+ break;
+ }
+ multiplier *= 2;
+ unpack_0(f(guess), f_current);
+ }
+ }
+
+ if (count)
+ {
+ min = guess;
+ if (multiplier > 16)
+ return (guess0 - guess) + bracket_root_towards_max(f, guess, f_current, min, max, count);
+ }
+ return guess0 - (max + min) / 2;
+ }
+
template <class Stepper, class F, class T>
T second_order_root_finder(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_iter) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
{
BOOST_MATH_STD_USING
- T f0(0), f1, f2;
+#ifdef BOOST_MATH_INSTRUMENT
+ std::cout << "Second order root iteration, guess = " << guess << ", min = " << min << ", max = " << max
+ << ", digits = " << digits << ", max_iter = " << max_iter << std::endl;
+#endif
+
+ T f0(0), f1, f2;
T result = guess;
T factor = ldexp(static_cast<T>(1.0), 1 - digits);
@@ -392,7 +519,7 @@ namespace detail{
{
// Oops zero derivative!!!
#ifdef BOOST_MATH_INSTRUMENT
- std::cout << "Second order root iteration, zero derivative found" << std::endl;
+ std::cout << "Second order root iteration, zero derivative found!" << std::endl;
#endif
detail::handle_zero_derivative(f, last_f0, f0, delta, result, guess, min, max);
}
@@ -429,7 +556,7 @@ namespace detail{
// last two steps haven't converged.
delta = (delta > 0) ? (result - min) / 2 : (result - max) / 2;
if ((result != 0) && (fabs(delta) > result))
- delta = sign(delta) * result; // protect against huge jumps!
+ delta = sign(delta) * fabs(result) * 0.9; // protect against huge jumps!
// reset delta2 so that this branch will *not* be taken on the
// next iteration:
delta2 = delta * 3;
@@ -459,10 +586,15 @@ namespace detail{
}
else
{
- delta = (guess - min) / 2;
- result = guess - delta;
- if((result == min) || (result == max))
+ if (fabs(float_distance(min, max)) < 2)
+ {
+ result = guess = (min + max) / 2;
break;
+ }
+ delta = bracket_root_towards_min(f, guess, f0, min, max, count);
+ result = guess - delta;
+ guess = min;
+ continue;
}
}
else if(result > max)
@@ -480,10 +612,15 @@ namespace detail{
}
else
{
- delta = (guess - max) / 2;
- result = guess - delta;
- if((result == min) || (result == max))
+ if (fabs(float_distance(min, max)) < 2)
+ {
+ result = guess = (min + max) / 2;
break;
+ }
+ delta = bracket_root_towards_max(f, guess, f0, min, max, count);
+ result = guess - delta;
+ guess = min;
+ continue;
}
}
// update brackets:
@@ -496,14 +633,12 @@ namespace detail{
max_iter -= count;
#ifdef BOOST_MATH_INSTRUMENT
- std::cout << "Second order root iteration, final count = " << max_iter << std::endl;
+ std::cout << "Second order root finder, final iteration count = " << max_iter << std::endl;
#endif
return result;
}
-
-}
-
+} // T second_order_root_finder
template <class F, class T>
T halley_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_iter) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
{
diff --git a/boost/math/tools/univariate_statistics.hpp b/boost/math/tools/univariate_statistics.hpp
index 226fdf46d2..387ff859ee 100644
--- a/boost/math/tools/univariate_statistics.hpp
+++ b/boost/math/tools/univariate_statistics.hpp
@@ -30,12 +30,47 @@ auto mean(ForwardIterator first, ForwardIterator last)
}
return mu;
}
- else
+ else if constexpr (std::is_same_v<typename std::iterator_traits<ForwardIterator>::iterator_category, std::random_access_iterator_tag>)
{
- Real mu = 0;
+ size_t elements = std::distance(first, last);
+ Real mu0 = 0;
+ Real mu1 = 0;
+ Real mu2 = 0;
+ Real mu3 = 0;
Real i = 1;
- for(auto it = first; it != last; ++it) {
- mu = mu + (*it - mu)/i;
+ auto end = last - (elements % 4);
+ for(auto it = first; it != end; it += 4) {
+ Real inv = Real(1)/i;
+ Real tmp0 = (*it - mu0);
+ Real tmp1 = (*(it+1) - mu1);
+ Real tmp2 = (*(it+2) - mu2);
+ Real tmp3 = (*(it+3) - mu3);
+ // please generate a vectorized fma here
+ mu0 += tmp0*inv;
+ mu1 += tmp1*inv;
+ mu2 += tmp2*inv;
+ mu3 += tmp3*inv;
+ i += 1;
+ }
+ Real num1 = Real(elements - (elements %4))/Real(4);
+ Real num2 = num1 + Real(elements % 4);
+
+ for (auto it = end; it != last; ++it)
+ {
+ mu3 += (*it-mu3)/i;
+ i += 1;
+ }
+
+ return (num1*(mu0+mu1+mu2) + num2*mu3)/Real(elements);
+ }
+ else
+ {
+ auto it = first;
+ Real mu = *it;
+ Real i = 2;
+ while(++it != last)
+ {
+ mu += (*it - mu)/i;
i += 1;
}
return mu;
diff --git a/boost/metaparse/config.hpp b/boost/metaparse/config.hpp
index 2e8e6a2931..f1af39e6b9 100644
--- a/boost/metaparse/config.hpp
+++ b/boost/metaparse/config.hpp
@@ -41,7 +41,15 @@
) \
&& (!defined BOOST_GCC || BOOST_GCC >= 40700)
-# define BOOST_METAPARSE_STD 2011
+# if !defined BOOST_NO_CXX14_CONSTEXPR
+
+# define BOOST_METAPARSE_STD 2014
+
+# else
+
+# define BOOST_METAPARSE_STD 2011
+
+# endif
# else
diff --git a/boost/metaparse/v1/cpp11/impl/any_of_c.hpp b/boost/metaparse/v1/cpp11/impl/any_of_c.hpp
new file mode 100644
index 0000000000..fcc3ea3a1c
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/any_of_c.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_ANY_OF_C_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_ANY_OF_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/cpp11/impl/or_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <char... Cs>
+ struct any_of_c
+ {
+ typedef any_of_c type;
+
+ template <class Chr>
+ struct apply : or_c<(Chr::type::value == Cs)...> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/impl/eval_later_result.hpp b/boost/metaparse/v1/cpp11/impl/eval_later_result.hpp
new file mode 100644
index 0000000000..e88616dcea
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/eval_later_result.hpp
@@ -0,0 +1,39 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_EVAL_LATER_RESULT_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_EVAL_LATER_RESULT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/get_position.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/less.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class R1, class R2>
+ struct eval_later_result :
+ boost::mpl::eval_if<
+ typename boost::mpl::less<
+ typename get_position<R2>::type,
+ typename get_position<R1>::type
+ >::type,
+ R1,
+ R2
+ >
+ {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/impl/is_none_c.hpp b/boost/metaparse/v1/cpp11/impl/is_none_c.hpp
new file mode 100644
index 0000000000..8e3afd6489
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/is_none_c.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_IS_NONE_C_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_IS_NONE_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/cpp11/impl/is_none_c_impl.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <char... Cs>
+ struct is_none_c
+ {
+ typedef is_none_c type;
+
+ template <class C>
+ struct apply : is_none_c_impl<C::type::value, Cs...> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/impl/is_none_c_impl.hpp b/boost/metaparse/v1/cpp11/impl/is_none_c_impl.hpp
new file mode 100644
index 0000000000..51fe7d878a
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/is_none_c_impl.hpp
@@ -0,0 +1,36 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_IS_NONE_C_IMPL_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_IS_NONE_C_IMPL_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mpl/bool.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <char D, char... Cs>
+ struct is_none_c_impl;
+
+ template <char D>
+ struct is_none_c_impl<D> : boost::mpl::bool_<true> {};
+
+ template <char D, char... Cs>
+ struct is_none_c_impl<D, D, Cs...> : boost::mpl::bool_<false> {};
+
+ template <char D, char C, char... Cs>
+ struct is_none_c_impl<D, C, Cs...> : is_none_c_impl<D, Cs...> {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/impl/or_c.hpp b/boost/metaparse/v1/cpp11/impl/or_c.hpp
new file mode 100644
index 0000000000..0e5ce0336f
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/or_c.hpp
@@ -0,0 +1,36 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_OR_C_HPP
+#define BOOST_METAPARSE_V1_CPP11_OR_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mpl/bool.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <bool... Bs>
+ struct or_c;
+
+ template <>
+ struct or_c<> : boost::mpl::false_ {};
+
+ template <bool... Bs>
+ struct or_c<true, Bs...> : boost::mpl::true_ {};
+
+ template <bool... Bs>
+ struct or_c<false, Bs...> : or_c<Bs...> {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/impl/push_front_result.hpp b/boost/metaparse/v1/cpp11/impl/push_front_result.hpp
new file mode 100644
index 0000000000..3a11ed7e69
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/impl/push_front_result.hpp
@@ -0,0 +1,36 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_PUSH_FRONT_RESULT_HPP
+#define BOOST_METAPARSE_V1_CPP11_IMPL_PUSH_FRONT_RESULT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2018.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/get_result.hpp>
+
+#include <boost/mpl/push_front.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class Value>
+ struct push_front_result
+ {
+ typedef push_front_result type;
+
+ template <class Seq>
+ struct apply :
+ boost::mpl::push_front<Seq, typename get_result<Value>::type>
+ {};
+ };
+ }
+ }
+ }
+}
+
+#endif
diff --git a/boost/metaparse/v1/cpp11/impl/remove_trailing_no_chars.hpp b/boost/metaparse/v1/cpp11/impl/remove_trailing_no_chars.hpp
deleted file mode 100644
index cdea6e4b7f..0000000000
--- a/boost/metaparse/v1/cpp11/impl/remove_trailing_no_chars.hpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef BOOST_METAPARSE_V1_CPP11_IMPL_REMOVE_TRAILING_NO_CHARS_HPP
-#define BOOST_METAPARSE_V1_CPP11_IMPL_REMOVE_TRAILING_NO_CHARS_HPP
-
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#include <boost/metaparse/v1/cpp11/string.hpp>
-#include <boost/metaparse/v1/impl/no_char.hpp>
-#include <boost/metaparse/v1/cpp11/impl/push_front_c.hpp>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- namespace impl
- {
- template <class S>
- struct remove_trailing_no_chars : S {};
-
- // this code assumes that BOOST_NO_CHARs are at the end of the string
- template <char... Cs>
- struct remove_trailing_no_chars<string<BOOST_NO_CHAR, Cs...>> :
- string<>
- {};
-
- template <char C, char... Cs>
- struct remove_trailing_no_chars<string<C, Cs...>> :
- push_front_c<typename remove_trailing_no_chars<string<Cs...>>::type,C>
- {};
-
-#ifdef _MSC_VER
- /*
- * These specialisations are needed to avoid an internal compiler error
- * in Visual C++ 12
- */
- template <char C>
- struct remove_trailing_no_chars<string<C>> : string<C> {};
-
- template <>
- struct remove_trailing_no_chars<string<BOOST_NO_CHAR>> : string<> {};
-
- template <>
- struct remove_trailing_no_chars<string<>> : string<> {};
-#endif
- }
- }
- }
-}
-
-#endif
-
diff --git a/boost/metaparse/v1/cpp11/impl/string_at.hpp b/boost/metaparse/v1/cpp11/impl/string_at.hpp
index 6540d56f65..ea0dfb9e91 100644
--- a/boost/metaparse/v1/cpp11/impl/string_at.hpp
+++ b/boost/metaparse/v1/cpp11/impl/string_at.hpp
@@ -6,8 +6,6 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/metaparse/v1/impl/no_char.hpp>
-
#include <boost/metaparse/limit_string_size.hpp>
namespace boost
@@ -19,12 +17,12 @@ namespace boost
namespace impl
{
template <int MaxLen, int Len, class T>
- constexpr int string_at(const T (&s)[Len], int n)
+ constexpr T string_at(const T (&s)[Len], int n)
{
// "MaxLen + 1" adds the \0 character of the string literal to the
// limit
static_assert(Len <= MaxLen + 1, "String literal is too long.");
- return n >= Len - 1 ? BOOST_NO_CHAR : s[n];
+ return n >= Len - 1 ? T() : s[n];
}
}
}
diff --git a/boost/metaparse/v1/cpp11/one_char_except.hpp b/boost/metaparse/v1/cpp11/one_char_except.hpp
new file mode 100644
index 0000000000..f7c3a28d19
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/one_char_except.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_ONE_CHAR_EXCEPT_HPP
+#define BOOST_METAPARSE_V1_CPP11_ONE_CHAR_EXCEPT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/error/unexpected_character.hpp>
+#include <boost/metaparse/v1/cpp11/impl/is_none_c.hpp>
+#include <boost/metaparse/v1/one_char.hpp>
+#include <boost/metaparse/v1/accept_when.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class... Cs>
+ struct one_char_except :
+ accept_when<
+ one_char,
+ impl::is_none_c<Cs::type::value...>,
+ error::unexpected_character
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/one_char_except_c.hpp b/boost/metaparse/v1/cpp11/one_char_except_c.hpp
new file mode 100644
index 0000000000..f1cf2ec84f
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/one_char_except_c.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_ONE_CHAR_EXCEPT_C_HPP
+#define BOOST_METAPARSE_V1_CPP11_ONE_CHAR_EXCEPT_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/error/unexpected_character.hpp>
+#include <boost/metaparse/v1/cpp11/impl/is_none_c.hpp>
+#include <boost/metaparse/v1/accept_when.hpp>
+#include <boost/metaparse/v1/one_char.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <char... Cs>
+ struct one_char_except_c :
+ accept_when<
+ one_char,
+ impl::is_none_c<Cs...>,
+ error::unexpected_character
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/one_of.hpp b/boost/metaparse/v1/cpp11/one_of.hpp
new file mode 100644
index 0000000000..d68eee16ad
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/one_of.hpp
@@ -0,0 +1,56 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_ONE_OF_HPP
+#define BOOST_METAPARSE_V1_CPP11_ONE_OF_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/fail.hpp>
+#include <boost/metaparse/v1/cpp11/impl/eval_later_result.hpp>
+#include <boost/metaparse/v1/error/none_of_the_expected_cases_found.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class... Ps>
+ struct one_of;
+
+ template <class P, class... Ps>
+ struct one_of<P, Ps...>
+ {
+ typedef one_of type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename P::template apply<S, Pos>>::type,
+ boost::mpl::eval_if<
+ typename is_error<
+ typename one_of<Ps...>::template apply<S, Pos>
+ >::type,
+ impl::eval_later_result<
+ typename P::template apply<S, Pos>,
+ typename one_of<Ps...>::template apply<S, Pos>
+ >,
+ typename one_of<Ps...>::template apply<S, Pos>
+ >,
+ typename P::template apply<S, Pos>
+ >
+ {};
+ };
+
+ template <>
+ struct one_of<> : fail<error::none_of_the_expected_cases_found> {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/one_of_c.hpp b/boost/metaparse/v1/cpp11/one_of_c.hpp
new file mode 100644
index 0000000000..4fa12cf6f4
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/one_of_c.hpp
@@ -0,0 +1,35 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_ONE_OF_C_HPP
+#define BOOST_METAPARSE_V1_CPP11_ONE_OF_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/one_char.hpp>
+#include <boost/metaparse/v1/accept_when.hpp>
+#include <boost/metaparse/v1/error/none_of_the_expected_cases_found.hpp>
+#include <boost/metaparse/v1/cpp11/impl/any_of_c.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <char... Cs>
+ struct one_of_c :
+ accept_when<
+ one_char,
+ impl::any_of_c<Cs...>,
+ error::none_of_the_expected_cases_found
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/repeated_one_of.hpp b/boost/metaparse/v1/cpp11/repeated_one_of.hpp
new file mode 100644
index 0000000000..ec788efe1f
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/repeated_one_of.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_REPEATED_ONE_OF_HPP
+#define BOOST_METAPARSE_V1_CPP11_REPEATED_ONE_OF_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/one_of.hpp>
+#include <boost/metaparse/v1/repeated.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class... Ps>
+ using repeated_one_of = repeated<one_of<Ps...>>;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/repeated_one_of1.hpp b/boost/metaparse/v1/cpp11/repeated_one_of1.hpp
new file mode 100644
index 0000000000..67e2cabefd
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/repeated_one_of1.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_REPEATED_ONE_OF1_HPP
+#define BOOST_METAPARSE_V1_CPP11_REPEATED_ONE_OF1_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/one_of.hpp>
+#include <boost/metaparse/v1/repeated1.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class... Ps>
+ using repeated_one_of1 = repeated1<one_of<Ps...>>;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp11/sequence.hpp b/boost/metaparse/v1/cpp11/sequence.hpp
new file mode 100644
index 0000000000..a9f4323783
--- /dev/null
+++ b/boost/metaparse/v1/cpp11/sequence.hpp
@@ -0,0 +1,62 @@
+#ifndef BOOST_METAPARSE_V1_CPP11_SEQUENCE_HPP
+#define BOOST_METAPARSE_V1_CPP11_SEQUENCE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2018.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/cpp11/impl/push_front_result.hpp>
+
+#include <boost/metaparse/v1/get_remaining.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/return_.hpp>
+#include <boost/metaparse/v1/transform.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class... Ps>
+ struct sequence;
+
+ template <>
+ struct sequence<> : return_<boost::mpl::vector<>> {};
+
+ template <class P, class... Ps>
+ struct sequence<P, Ps...>
+ {
+ private:
+ template <class Res>
+ struct apply_unchecked :
+ transform<
+ sequence<Ps...>,
+ impl::push_front_result<Res>
+ >::template apply<
+ typename get_remaining<Res>::type,
+ typename get_position<Res>::type
+ >
+ {};
+ public:
+ typedef sequence type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename P::template apply<S, Pos>>::type,
+ typename P::template apply<S, Pos>,
+ apply_unchecked<typename P::template apply<S, Pos>>
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
diff --git a/boost/metaparse/v1/cpp11/string.hpp b/boost/metaparse/v1/cpp11/string.hpp
index c2bd95cb19..8dbef5cb2c 100644
--- a/boost/metaparse/v1/cpp11/string.hpp
+++ b/boost/metaparse/v1/cpp11/string.hpp
@@ -206,8 +206,6 @@ namespace boost
}
}
-#include <boost/metaparse/v1/cpp11/impl/remove_trailing_no_chars.hpp>
-
#if __clang__
# if __has_extension(cxx_string_literal_templates)
# define BOOST_METAPARSE_V1_STRING(...) ::boost::metaparse::string<__VA_ARGS__>
diff --git a/boost/metaparse/v1/cpp14/impl/any_of_c.hpp b/boost/metaparse/v1/cpp14/impl/any_of_c.hpp
new file mode 100644
index 0000000000..14fede51c4
--- /dev/null
+++ b/boost/metaparse/v1/cpp14/impl/any_of_c.hpp
@@ -0,0 +1,55 @@
+#ifndef BOOST_METAPARSE_V1_CPP14_IMPL_ANY_OF_C_HPP
+#define BOOST_METAPARSE_V1_CPP14_IMPL_ANY_OF_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mpl/bool.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <char... Cs>
+ struct any_of_c
+ {
+ typedef any_of_c type;
+
+ static constexpr bool run(char c_)
+ {
+ const bool values[] = {(c_ == Cs)...};
+ for (const bool* i = values; i != values + sizeof...(Cs); ++i)
+ {
+ if (*i)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <class Chr>
+ struct apply : boost::mpl::bool_<any_of_c::run(Chr::type::value)> {};
+ };
+
+ template <>
+ struct any_of_c<>
+ {
+ typedef any_of_c type;
+
+ template <class>
+ struct apply : boost::mpl::false_ {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp14/one_of_c.hpp b/boost/metaparse/v1/cpp14/one_of_c.hpp
new file mode 100644
index 0000000000..fdfcda0b08
--- /dev/null
+++ b/boost/metaparse/v1/cpp14/one_of_c.hpp
@@ -0,0 +1,35 @@
+#ifndef BOOST_METAPARSE_V1_CPP14_ONE_OF_C_HPP
+#define BOOST_METAPARSE_V1_CPP14_ONE_OF_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/one_char.hpp>
+#include <boost/metaparse/v1/accept_when.hpp>
+#include <boost/metaparse/v1/error/none_of_the_expected_cases_found.hpp>
+#include <boost/metaparse/v1/cpp14/impl/any_of_c.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <char... Cs>
+ struct one_of_c :
+ accept_when<
+ one_char,
+ impl::any_of_c<Cs...>,
+ error::none_of_the_expected_cases_found
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/is_any.hpp b/boost/metaparse/v1/cpp98/impl/is_none.hpp
index 23122b35ce..758658640a 100644
--- a/boost/metaparse/v1/impl/is_any.hpp
+++ b/boost/metaparse/v1/cpp98/impl/is_none.hpp
@@ -1,5 +1,5 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_IS_ANY_HPP
-#define BOOST_METAPARSE_V1_IMPL_IS_ANY_HPP
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_IS_NONE_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_IS_NONE_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
// Distributed under the Boost Software License, Version 1.0.
@@ -25,18 +25,18 @@ namespace boost
namespace impl
{
template <class Stub = int>
- struct is_any0
+ struct is_none0
{
template <class C>
struct apply : boost::mpl::true_ {};
};
- #ifdef BOOST_METAPARSE_DEFINE_IS_ANY
- # error BOOST_METAPARSE_DEFINE_IS_ANY already defined
+ #ifdef BOOST_METAPARSE_DEFINE_IS_NONE
+ # error BOOST_METAPARSE_DEFINE_IS_NONE already defined
#endif
- #define BOOST_METAPARSE_DEFINE_IS_ANY(z, n, unused) \
+ #define BOOST_METAPARSE_DEFINE_IS_NONE(z, n, unused) \
template <BOOST_PP_ENUM_PARAMS(n, class T)> \
- struct BOOST_PP_CAT(is_any, n) \
+ struct BOOST_PP_CAT(is_none, n) \
{ \
template <class C> \
struct apply : \
@@ -46,7 +46,7 @@ namespace boost
== BOOST_PP_CAT(T, BOOST_PP_DEC(n))::type::value \
>, \
boost::mpl::false_, \
- typename BOOST_PP_CAT(is_any, BOOST_PP_DEC(n))< \
+ typename BOOST_PP_CAT(is_none, BOOST_PP_DEC(n))< \
BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(n), T) \
>::template apply<C> \
> \
@@ -56,11 +56,11 @@ namespace boost
BOOST_PP_REPEAT_FROM_TO(
1,
BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE,
- BOOST_METAPARSE_DEFINE_IS_ANY,
+ BOOST_METAPARSE_DEFINE_IS_NONE,
~
)
- #undef BOOST_METAPARSE_DEFINE_IS_ANY
+ #undef BOOST_METAPARSE_DEFINE_IS_NONE
}
}
}
diff --git a/boost/metaparse/v1/impl/later_result.hpp b/boost/metaparse/v1/cpp98/impl/later_result.hpp
index 69c2e5b89a..98afaf12aa 100644
--- a/boost/metaparse/v1/impl/later_result.hpp
+++ b/boost/metaparse/v1/cpp98/impl/later_result.hpp
@@ -1,5 +1,5 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_LATER_RESULT_HPP
-#define BOOST_METAPARSE_V1_IMPL_LATER_RESULT_HPP
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_LATER_RESULT_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_LATER_RESULT_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
// Distributed under the Boost Software License, Version 1.0.
diff --git a/boost/metaparse/v1/impl/one_char_except_not_used.hpp b/boost/metaparse/v1/cpp98/impl/one_char_except_not_used.hpp
index 249fcdd725..0bc0781b3f 100644
--- a/boost/metaparse/v1/impl/one_char_except_not_used.hpp
+++ b/boost/metaparse/v1/cpp98/impl/one_char_except_not_used.hpp
@@ -1,5 +1,5 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_ONE_CHAR_EXCEPT_NOT_USED_HPP
-#define BOOST_METAPARSE_V1_IMPL_ONE_CHAR_EXCEPT_NOT_USED_HPP
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_ONE_CHAR_EXCEPT_NOT_USED_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_ONE_CHAR_EXCEPT_NOT_USED_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
// Distributed under the Boost Software License, Version 1.0.
diff --git a/boost/metaparse/v1/impl/one_of.hpp b/boost/metaparse/v1/cpp98/impl/one_of.hpp
index e5b53e2e5c..26fa8530e1 100644
--- a/boost/metaparse/v1/impl/one_of.hpp
+++ b/boost/metaparse/v1/cpp98/impl/one_of.hpp
@@ -9,7 +9,7 @@
#include <boost/metaparse/v1/error/none_of_the_expected_cases_found.hpp>
#include <boost/metaparse/v1/fail.hpp>
-#include <boost/metaparse/v1/impl/one_of_fwd_op.hpp>
+#include <boost/metaparse/v1/cpp98/impl/one_of_fwd_op.hpp>
#include <boost/mpl/fold.hpp>
diff --git a/boost/metaparse/v1/impl/one_of_fwd_op.hpp b/boost/metaparse/v1/cpp98/impl/one_of_fwd_op.hpp
index 97d4658381..a52ec112d6 100644
--- a/boost/metaparse/v1/impl/one_of_fwd_op.hpp
+++ b/boost/metaparse/v1/cpp98/impl/one_of_fwd_op.hpp
@@ -7,7 +7,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/metaparse/v1/is_error.hpp>
-#include <boost/metaparse/v1/impl/later_result.hpp>
+#include <boost/metaparse/v1/cpp98/impl/later_result.hpp>
#include <boost/mpl/eval_if.hpp>
diff --git a/boost/metaparse/v1/impl/sequence.hpp b/boost/metaparse/v1/cpp98/impl/sequence.hpp
index c500cdf046..7f28766441 100644
--- a/boost/metaparse/v1/impl/sequence.hpp
+++ b/boost/metaparse/v1/cpp98/impl/sequence.hpp
@@ -1,12 +1,12 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_SEQUENCE_HPP
-#define BOOST_METAPARSE_V1_IMPL_SEQUENCE_HPP
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_SEQUENCE_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_SEQUENCE_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/metaparse/v1/impl/sequence_impl.hpp>
+#include <boost/metaparse/v1/cpp98/impl/sequence_impl.hpp>
#include <boost/metaparse/limit_sequence_size.hpp>
#include <boost/mpl/vector.hpp>
diff --git a/boost/metaparse/v1/impl/sequence_impl.hpp b/boost/metaparse/v1/cpp98/impl/sequence_impl.hpp
index d3310ed8af..c83ddcd9a1 100644
--- a/boost/metaparse/v1/impl/sequence_impl.hpp
+++ b/boost/metaparse/v1/cpp98/impl/sequence_impl.hpp
@@ -1,5 +1,5 @@
-#ifndef BOOST_METAPARSE_V1_IMPL_SEQUENCE_IMPL_HPP
-#define BOOST_METAPARSE_V1_IMPL_SEQUENCE_IMPL_HPP
+#ifndef BOOST_METAPARSE_V1_CPP98_IMPL_SEQUENCE_IMPL_HPP
+#define BOOST_METAPARSE_V1_CPP98_IMPL_SEQUENCE_IMPL_HPP
// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
// Distributed under the Boost Software License, Version 1.0.
diff --git a/boost/metaparse/v1/cpp98/one_char_except.hpp b/boost/metaparse/v1/cpp98/one_char_except.hpp
new file mode 100644
index 0000000000..330b593dcd
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/one_char_except.hpp
@@ -0,0 +1,84 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_ONE_CHAR_EXCEPT_HPP
+#define BOOST_METAPARSE_V1_CPP98_ONE_CHAR_EXCEPT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/v1/error/unexpected_character.hpp>
+#include <boost/metaparse/v1/cpp98/impl/is_none.hpp>
+#include <boost/metaparse/v1/cpp98/impl/one_char_except_not_used.hpp>
+#include <boost/metaparse/v1/one_char.hpp>
+#include <boost/metaparse/v1/accept_when.hpp>
+#include <boost/metaparse/limit_one_char_except_size.hpp>
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/arithmetic/mul.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
+ BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE,
+ class C,
+ impl::one_char_except_not_used
+ )
+ >
+ struct one_char_except;
+
+ #ifdef MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE
+ # error MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE already defined
+ #endif
+ #define MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE(z, n, unused) \
+ template <BOOST_PP_ENUM_PARAMS(n, class T)> \
+ struct one_char_except< \
+ BOOST_PP_ENUM_PARAMS(n, T) \
+ BOOST_PP_COMMA_IF( \
+ BOOST_PP_MUL( \
+ n, \
+ BOOST_PP_SUB( \
+ BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE), \
+ n \
+ ) \
+ ) \
+ ) \
+ BOOST_PP_ENUM( \
+ BOOST_PP_SUB( \
+ BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE), \
+ n \
+ ), \
+ impl::one_char_except_not_used BOOST_PP_TUPLE_EAT(3), \
+ ~ \
+ ) \
+ > :\
+ accept_when< \
+ one_char, \
+ impl::BOOST_PP_CAT(is_none, n)<BOOST_PP_ENUM_PARAMS(n, T)>, \
+ error::unexpected_character \
+ > \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE,
+ MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE,
+ ~
+ )
+
+ #undef MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp98/one_char_except_c.hpp b/boost/metaparse/v1/cpp98/one_char_except_c.hpp
new file mode 100644
index 0000000000..5556039a65
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/one_char_except_c.hpp
@@ -0,0 +1,96 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_ONE_CHAR_EXCEPT_C_HPP
+#define BOOST_METAPARSE_V1_CPP98_ONE_CHAR_EXCEPT_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 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)
+
+#include <boost/metaparse/limit_one_char_except_size.hpp>
+#include <boost/metaparse/v1/error/unexpected_character.hpp>
+#include <boost/metaparse/v1/cpp98/impl/is_none.hpp>
+#include <boost/metaparse/v1/accept_when.hpp>
+#include <boost/metaparse/v1/one_char.hpp>
+
+#include <boost/mpl/char.hpp>
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/arithmetic/mul.hpp>
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
+ BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE,
+ int C,
+ 1024
+ )
+ >
+ struct one_char_except_c;
+
+ #ifdef BOOST_METAPARSE_WRAP
+ # error BOOST_METAPARSE_WRAP already defined
+ #endif
+ #define BOOST_METAPARSE_WRAP(z, n, unused) \
+ boost::mpl::char_<BOOST_PP_CAT(C, n)>
+
+ #ifdef MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE
+ # error MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE already defined
+ #endif
+ #define MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE(z, n, unused) \
+ template <BOOST_PP_ENUM_PARAMS(n, int C)> \
+ struct one_char_except_c< \
+ BOOST_PP_ENUM_PARAMS(n, C) \
+ BOOST_PP_COMMA_IF( \
+ BOOST_PP_MUL( \
+ n, \
+ BOOST_PP_SUB( \
+ BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE), \
+ n \
+ )\
+ ) \
+ ) \
+ BOOST_PP_ENUM( \
+ BOOST_PP_SUB( \
+ BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE), \
+ n \
+ ), \
+ 1024 BOOST_PP_TUPLE_EAT(3), \
+ ~ \
+ ) \
+ > : \
+ accept_when< \
+ one_char, \
+ impl::BOOST_PP_CAT(is_none, n)< \
+ BOOST_PP_ENUM(n, BOOST_METAPARSE_WRAP, ~) \
+ >, \
+ error::unexpected_character \
+ > \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE,
+ MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE,
+ ~
+ )
+
+ #undef MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE
+ #undef BOOST_METAPARSE_WRAP
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp98/one_of.hpp b/boost/metaparse/v1/cpp98/one_of.hpp
new file mode 100644
index 0000000000..d40b8ff085
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/one_of.hpp
@@ -0,0 +1,42 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_ONE_OF_HPP
+#define BOOST_METAPARSE_V1_CPP98_ONE_OF_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2009 - 2010.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/cpp98/impl/one_of.hpp>
+#include <boost/metaparse/limit_one_of_size.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
+ BOOST_METAPARSE_LIMIT_ONE_OF_SIZE,
+ class P,
+ boost::mpl::na
+ )
+ >
+ struct one_of :
+ impl::one_of<
+ boost::mpl::vector<
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_ONE_OF_SIZE, P)
+ >
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp98/one_of_c.hpp b/boost/metaparse/v1/cpp98/one_of_c.hpp
new file mode 100644
index 0000000000..9a13a331bf
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/one_of_c.hpp
@@ -0,0 +1,81 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_ONE_OF_C_HPP
+#define BOOST_METAPARSE_V1_CPP98_ONE_OF_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/one_of.hpp>
+#include <boost/metaparse/v1/lit_c.hpp>
+#include <boost/metaparse/limit_one_of_size.hpp>
+
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+#include <climits>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ #ifdef BOOST_NO_SCALAR_VALUE
+ # error BOOST_NO_SCALAR_VALUE already defined
+ #endif
+ #define BOOST_NO_SCALAR_VALUE LONG_MAX
+
+ template <
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
+ BOOST_METAPARSE_LIMIT_ONE_OF_SIZE,
+ long C,
+ BOOST_NO_SCALAR_VALUE
+ )
+ >
+ struct one_of_c;
+
+ #ifdef BOOST_METAPARSE_ONE_OF_C_LIT
+ # error BOOST_METAPARSE_ONE_OF_C_LIT already defined
+ #endif
+ #define BOOST_METAPARSE_ONE_OF_C_LIT(z, n, unused) lit_c<BOOST_PP_CAT(C, n)>
+
+ #ifdef BOOST_METAPARSE_ONE_OF_C_CASE
+ # error BOOST_METAPARSE_ONE_OF_C_CASE already defined
+ #endif
+ #define BOOST_METAPARSE_ONE_OF_C_CASE(z, n, unused) \
+ template <BOOST_PP_ENUM_PARAMS(n, long C)> \
+ struct \
+ one_of_c< \
+ BOOST_PP_ENUM_PARAMS(n, C) \
+ BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_ENUM( \
+ BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_ONE_OF_SIZE, n), \
+ BOOST_NO_SCALAR_VALUE BOOST_PP_TUPLE_EAT(3), \
+ ~ \
+ ) \
+ > : \
+ one_of< BOOST_PP_ENUM(n, BOOST_METAPARSE_ONE_OF_C_LIT, ~) > \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_ONE_OF_SIZE,
+ BOOST_METAPARSE_ONE_OF_C_CASE,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_ONE_OF_C_CASE
+ #undef BOOST_METAPARSE_ONE_OF_C_LIT
+ #undef BOOST_NO_SCALAR_VALUE
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp98/repeated_one_of.hpp b/boost/metaparse/v1/cpp98/repeated_one_of.hpp
new file mode 100644
index 0000000000..eb874dfd39
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/repeated_one_of.hpp
@@ -0,0 +1,45 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_REPEATED_ONE_OF_HPP
+#define BOOST_METAPARSE_V1_CPP98_REPEATED_ONE_OF_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2010.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/limit_one_of_size.hpp>
+#include <boost/metaparse/v1/cpp98/impl/one_of.hpp>
+#include <boost/metaparse/v1/repeated.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
+ BOOST_METAPARSE_LIMIT_ONE_OF_SIZE,
+ class P,
+ boost::mpl::na
+ )
+ >
+ struct repeated_one_of :
+ repeated<
+ impl::one_of<
+ boost::mpl::vector<
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_ONE_OF_SIZE, P)
+ >
+ >
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp98/repeated_one_of1.hpp b/boost/metaparse/v1/cpp98/repeated_one_of1.hpp
new file mode 100644
index 0000000000..abda799b7d
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/repeated_one_of1.hpp
@@ -0,0 +1,45 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_REPEATED_ONE_OF1_HPP
+#define BOOST_METAPARSE_V1_CPP98_REPEATED_ONE_OF1_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2010.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/limit_one_of_size.hpp>
+#include <boost/metaparse/v1/cpp98/impl/one_of.hpp>
+#include <boost/metaparse/v1/repeated1.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
+ BOOST_METAPARSE_LIMIT_ONE_OF_SIZE,
+ class P,
+ boost::mpl::na
+ )
+ >
+ struct repeated_one_of1 :
+ repeated1<
+ impl::one_of<
+ boost::mpl::vector<
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_ONE_OF_SIZE, P)
+ >
+ >
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/cpp98/sequence.hpp b/boost/metaparse/v1/cpp98/sequence.hpp
new file mode 100644
index 0000000000..6aae835801
--- /dev/null
+++ b/boost/metaparse/v1/cpp98/sequence.hpp
@@ -0,0 +1,64 @@
+#ifndef BOOST_METAPARSE_V1_CPP98_SEQUENCE_HPP
+#define BOOST_METAPARSE_V1_CPP98_SEQUENCE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2009 - 2010.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/cpp98/impl/sequence.hpp>
+
+#include <boost/preprocessor/comma_if.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
+ BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
+ class P,
+ boost::mpl::na
+ )
+ >
+ struct sequence;
+
+ #ifdef BOOST_METAPARSE_SEQUENCE_N
+ # error BOOST_METAPARSE_SEQUENCE_N already defined
+ #endif
+ #define BOOST_METAPARSE_SEQUENCE_N(z, n, unused) \
+ template <BOOST_PP_ENUM_PARAMS(n, class P)> \
+ struct sequence< \
+ BOOST_PP_ENUM_PARAMS(n, P) \
+ BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_ENUM( \
+ BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE, n), \
+ boost::mpl::na BOOST_PP_TUPLE_EAT(3), \
+ ~ \
+ ) \
+ > : impl::BOOST_PP_CAT(sequence, n)<BOOST_PP_ENUM_PARAMS(n, P)> \
+ {};
+
+ BOOST_PP_REPEAT_FROM_TO(
+ 1,
+ BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
+ BOOST_METAPARSE_SEQUENCE_N,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_SEQUENCE_N
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/one_char_except.hpp b/boost/metaparse/v1/one_char_except.hpp
index c859ab23f3..266d8d720a 100644
--- a/boost/metaparse/v1/one_char_except.hpp
+++ b/boost/metaparse/v1/one_char_except.hpp
@@ -1,85 +1,18 @@
#ifndef BOOST_METAPARSE_V1_ONE_CHAR_EXCEPT_HPP
#define BOOST_METAPARSE_V1_ONE_CHAR_EXCEPT_HPP
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 2011.
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/metaparse/v1/error/unexpected_character.hpp>
-#include <boost/metaparse/v1/impl/is_any.hpp>
-#include <boost/metaparse/v1/impl/one_char_except_not_used.hpp>
-#include <boost/metaparse/v1/one_char.hpp>
-#include <boost/metaparse/v1/accept_when.hpp>
-#include <boost/metaparse/v1/define_error.hpp>
-#include <boost/metaparse/limit_one_char_except_size.hpp>
+#include <boost/metaparse/config.hpp>
-#include <boost/preprocessor/cat.hpp>
-#include <boost/preprocessor/arithmetic/dec.hpp>
-#include <boost/preprocessor/arithmetic/mul.hpp>
-#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
-#include <boost/preprocessor/repetition/repeat.hpp>
-#include <boost/preprocessor/repetition/enum.hpp>
-#include <boost/preprocessor/punctuation/comma_if.hpp>
-#include <boost/preprocessor/tuple/eat.hpp>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- template <
- BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
- BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE,
- class C,
- impl::one_char_except_not_used
- )
- >
- struct one_char_except;
-
- #ifdef MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE
- # error MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE already defined
- #endif
- #define MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE(z, n, unused) \
- template <BOOST_PP_ENUM_PARAMS(n, class T)> \
- struct one_char_except< \
- BOOST_PP_ENUM_PARAMS(n, T) \
- BOOST_PP_COMMA_IF( \
- BOOST_PP_MUL( \
- n, \
- BOOST_PP_SUB( \
- BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE), \
- n \
- ) \
- ) \
- ) \
- BOOST_PP_ENUM( \
- BOOST_PP_SUB( \
- BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE), \
- n \
- ), \
- impl::one_char_except_not_used BOOST_PP_TUPLE_EAT(3), \
- ~ \
- ) \
- > :\
- accept_when< \
- one_char, \
- impl::BOOST_PP_CAT(is_any, n)<BOOST_PP_ENUM_PARAMS(n, T)>, \
- error::unexpected_character \
- > \
- {};
-
- BOOST_PP_REPEAT(
- BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE,
- MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE,
- ~
- )
-
- #undef MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE
- }
- }
-}
+#if BOOST_METAPARSE_STD >= 2011
+# include <boost/metaparse/v1/cpp11/one_char_except.hpp>
+#else
+# include <boost/metaparse/v1/cpp98/one_char_except.hpp>
+#endif
#endif
diff --git a/boost/metaparse/v1/one_char_except_c.hpp b/boost/metaparse/v1/one_char_except_c.hpp
index 780cb5924f..0c12a2a323 100644
--- a/boost/metaparse/v1/one_char_except_c.hpp
+++ b/boost/metaparse/v1/one_char_except_c.hpp
@@ -1,96 +1,18 @@
#ifndef BOOST_METAPARSE_V1_ONE_CHAR_EXCEPT_C_HPP
#define BOOST_METAPARSE_V1_ONE_CHAR_EXCEPT_C_HPP
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 2011.
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/metaparse/limit_one_char_except_size.hpp>
-#include <boost/metaparse/v1/error/unexpected_character.hpp>
-#include <boost/metaparse/v1/impl/is_any.hpp>
-#include <boost/metaparse/v1/accept_when.hpp>
-#include <boost/metaparse/v1/one_char.hpp>
+#include <boost/metaparse/config.hpp>
-#include <boost/mpl/char.hpp>
-
-#include <boost/preprocessor/cat.hpp>
-#include <boost/preprocessor/arithmetic/sub.hpp>
-#include <boost/preprocessor/arithmetic/mul.hpp>
-#include <boost/preprocessor/arithmetic/dec.hpp>
-#include <boost/preprocessor/repetition/repeat.hpp>
-#include <boost/preprocessor/repetition/enum.hpp>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
-#include <boost/preprocessor/punctuation/comma_if.hpp>
-#include <boost/preprocessor/tuple/eat.hpp>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- template <
- BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
- BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE,
- int C,
- 1024
- )
- >
- struct one_char_except_c;
-
- #ifdef BOOST_METAPARSE_WRAP
- # error BOOST_METAPARSE_WRAP already defined
- #endif
- #define BOOST_METAPARSE_WRAP(z, n, unused) \
- boost::mpl::char_<BOOST_PP_CAT(C, n)>
-
- #ifdef MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE
- # error MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE already defined
- #endif
- #define MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE(z, n, unused) \
- template <BOOST_PP_ENUM_PARAMS(n, int C)> \
- struct one_char_except_c< \
- BOOST_PP_ENUM_PARAMS(n, C) \
- BOOST_PP_COMMA_IF( \
- BOOST_PP_MUL( \
- n, \
- BOOST_PP_SUB( \
- BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE), \
- n \
- )\
- ) \
- ) \
- BOOST_PP_ENUM( \
- BOOST_PP_SUB( \
- BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE), \
- n \
- ), \
- 1024 BOOST_PP_TUPLE_EAT(3), \
- ~ \
- ) \
- > : \
- accept_when< \
- one_char, \
- impl::BOOST_PP_CAT(is_any, n)< \
- BOOST_PP_ENUM(n, BOOST_METAPARSE_WRAP, ~) \
- >, \
- error::unexpected_character \
- > \
- {};
-
- BOOST_PP_REPEAT(
- BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE,
- MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE,
- ~
- )
-
- #undef MPLLBIS_METAPARSE_ONE_CHAR_EXCEPT_CASE
- #undef BOOST_METAPARSE_WRAP
- }
- }
-}
+#if BOOST_METAPARSE_STD >= 2011
+# include <boost/metaparse/v1/cpp11/one_char_except_c.hpp>
+#else
+# include <boost/metaparse/v1/cpp98/one_char_except_c.hpp>
+#endif
#endif
diff --git a/boost/metaparse/v1/one_of.hpp b/boost/metaparse/v1/one_of.hpp
index d48db4c4c0..409d58d992 100644
--- a/boost/metaparse/v1/one_of.hpp
+++ b/boost/metaparse/v1/one_of.hpp
@@ -1,42 +1,18 @@
#ifndef BOOST_METAPARSE_V1_ONE_OF_HPP
#define BOOST_METAPARSE_V1_ONE_OF_HPP
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 2009 - 2010.
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/metaparse/v1/impl/one_of.hpp>
-#include <boost/metaparse/limit_one_of_size.hpp>
+#include <boost/metaparse/config.hpp>
-#include <boost/mpl/vector.hpp>
-
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- template <
- BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
- BOOST_METAPARSE_LIMIT_ONE_OF_SIZE,
- class P,
- boost::mpl::na
- )
- >
- struct one_of :
- impl::one_of<
- boost::mpl::vector<
- BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_ONE_OF_SIZE, P)
- >
- >
- {};
- }
- }
-}
+#if BOOST_METAPARSE_STD >= 2011
+# include <boost/metaparse/v1/cpp11/one_of.hpp>
+#else
+# include <boost/metaparse/v1/cpp98/one_of.hpp>
+#endif
#endif
diff --git a/boost/metaparse/v1/one_of_c.hpp b/boost/metaparse/v1/one_of_c.hpp
index ff7251a4e0..1f0e378d69 100644
--- a/boost/metaparse/v1/one_of_c.hpp
+++ b/boost/metaparse/v1/one_of_c.hpp
@@ -1,80 +1,20 @@
#ifndef BOOST_METAPARSE_V1_ONE_OF_C_HPP
#define BOOST_METAPARSE_V1_ONE_OF_C_HPP
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/metaparse/v1/one_of.hpp>
-#include <boost/metaparse/v1/lit_c.hpp>
+#include <boost/metaparse/config.hpp>
-#include <boost/preprocessor/arithmetic/sub.hpp>
-#include <boost/preprocessor/cat.hpp>
-#include <boost/preprocessor/punctuation/comma_if.hpp>
-#include <boost/preprocessor/repetition/enum.hpp>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
-#include <boost/preprocessor/repetition/repeat.hpp>
-#include <boost/preprocessor/tuple/eat.hpp>
-
-#include <climits>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- #ifdef BOOST_NO_SCALAR_VALUE
- # error BOOST_NO_SCALAR_VALUE already defined
- #endif
- #define BOOST_NO_SCALAR_VALUE LONG_MAX
-
- template <
- BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
- BOOST_METAPARSE_LIMIT_ONE_OF_SIZE,
- long C,
- BOOST_NO_SCALAR_VALUE
- )
- >
- struct one_of_c;
-
- #ifdef BOOST_METAPARSE_ONE_OF_C_LIT
- # error BOOST_METAPARSE_ONE_OF_C_LIT already defined
- #endif
- #define BOOST_METAPARSE_ONE_OF_C_LIT(z, n, unused) lit_c<BOOST_PP_CAT(C, n)>
-
- #ifdef BOOST_METAPARSE_ONE_OF_C_CASE
- # error BOOST_METAPARSE_ONE_OF_C_CASE already defined
- #endif
- #define BOOST_METAPARSE_ONE_OF_C_CASE(z, n, unused) \
- template <BOOST_PP_ENUM_PARAMS(n, long C)> \
- struct \
- one_of_c< \
- BOOST_PP_ENUM_PARAMS(n, C) \
- BOOST_PP_COMMA_IF(n) \
- BOOST_PP_ENUM( \
- BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_ONE_OF_SIZE, n), \
- BOOST_NO_SCALAR_VALUE BOOST_PP_TUPLE_EAT(3), \
- ~ \
- ) \
- > : \
- one_of< BOOST_PP_ENUM(n, BOOST_METAPARSE_ONE_OF_C_LIT, ~) > \
- {};
-
- BOOST_PP_REPEAT(
- BOOST_METAPARSE_LIMIT_ONE_OF_SIZE,
- BOOST_METAPARSE_ONE_OF_C_CASE,
- ~
- )
-
- #undef BOOST_METAPARSE_ONE_OF_C_CASE
- #undef BOOST_METAPARSE_ONE_OF_C_LIT
- #undef BOOST_NO_SCALAR_VALUE
- }
- }
-}
+#if BOOST_METAPARSE_STD >= 2014
+# include <boost/metaparse/v1/cpp14/one_of_c.hpp>
+#elif BOOST_METAPARSE_STD >= 2011
+# include <boost/metaparse/v1/cpp11/one_of_c.hpp>
+#else
+# include <boost/metaparse/v1/cpp98/one_of_c.hpp>
+#endif
#endif
diff --git a/boost/metaparse/v1/repeated_one_of.hpp b/boost/metaparse/v1/repeated_one_of.hpp
index 3296030b62..39bc03162b 100644
--- a/boost/metaparse/v1/repeated_one_of.hpp
+++ b/boost/metaparse/v1/repeated_one_of.hpp
@@ -1,45 +1,18 @@
#ifndef BOOST_METAPARSE_V1_REPEATED_ONE_OF_HPP
#define BOOST_METAPARSE_V1_REPEATED_ONE_OF_HPP
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 2010.
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/metaparse/limit_one_of_size.hpp>
-#include <boost/metaparse/v1/impl/one_of.hpp>
-#include <boost/metaparse/v1/repeated.hpp>
+#include <boost/metaparse/config.hpp>
-#include <boost/mpl/vector.hpp>
-
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- template <
- BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
- BOOST_METAPARSE_LIMIT_ONE_OF_SIZE,
- class P,
- boost::mpl::na
- )
- >
- struct repeated_one_of :
- repeated<
- impl::one_of<
- boost::mpl::vector<
- BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_ONE_OF_SIZE, P)
- >
- >
- >
- {};
- }
- }
-}
+#if BOOST_METAPARSE_STD >= 2011
+# include <boost/metaparse/v1/cpp11/repeated_one_of.hpp>
+#else
+# include <boost/metaparse/v1/cpp98/repeated_one_of.hpp>
+#endif
#endif
diff --git a/boost/metaparse/v1/repeated_one_of1.hpp b/boost/metaparse/v1/repeated_one_of1.hpp
index 2d305d2abd..a886c77edf 100644
--- a/boost/metaparse/v1/repeated_one_of1.hpp
+++ b/boost/metaparse/v1/repeated_one_of1.hpp
@@ -1,45 +1,18 @@
#ifndef BOOST_METAPARSE_V1_REPEATED_ONE_OF1_HPP
#define BOOST_METAPARSE_V1_REPEATED_ONE_OF1_HPP
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 2010.
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2017.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/metaparse/limit_one_of_size.hpp>
-#include <boost/metaparse/v1/impl/one_of.hpp>
-#include <boost/metaparse/v1/repeated1.hpp>
+#include <boost/metaparse/config.hpp>
-#include <boost/mpl/vector.hpp>
-
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- template <
- BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
- BOOST_METAPARSE_LIMIT_ONE_OF_SIZE,
- class P,
- boost::mpl::na
- )
- >
- struct repeated_one_of1 :
- repeated1<
- impl::one_of<
- boost::mpl::vector<
- BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_ONE_OF_SIZE, P)
- >
- >
- >
- {};
- }
- }
-}
+#if BOOST_METAPARSE_STD >= 2011
+# include <boost/metaparse/v1/cpp11/repeated_one_of1.hpp>
+#else
+# include <boost/metaparse/v1/cpp98/repeated_one_of1.hpp>
+#endif
#endif
diff --git a/boost/metaparse/v1/sequence.hpp b/boost/metaparse/v1/sequence.hpp
index f25c632fbd..0e4845d399 100644
--- a/boost/metaparse/v1/sequence.hpp
+++ b/boost/metaparse/v1/sequence.hpp
@@ -1,64 +1,18 @@
#ifndef BOOST_METAPARSE_V1_SEQUENCE_HPP
#define BOOST_METAPARSE_V1_SEQUENCE_HPP
-// Copyright Abel Sinkovics (abel@sinkovics.hu) 2009 - 2010.
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2018.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/metaparse/v1/impl/sequence.hpp>
+#include <boost/metaparse/config.hpp>
-#include <boost/preprocessor/comma_if.hpp>
-#include <boost/preprocessor/repetition/repeat_from_to.hpp>
-#include <boost/preprocessor/repetition/enum.hpp>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
-#include <boost/preprocessor/arithmetic/sub.hpp>
-#include <boost/preprocessor/cat.hpp>
-#include <boost/preprocessor/tuple/eat.hpp>
-
-namespace boost
-{
- namespace metaparse
- {
- namespace v1
- {
- template <
- BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
- BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
- class P,
- boost::mpl::na
- )
- >
- struct sequence;
-
- #ifdef BOOST_METAPARSE_SEQUENCE_N
- # error BOOST_METAPARSE_SEQUENCE_N already defined
- #endif
- #define BOOST_METAPARSE_SEQUENCE_N(z, n, unused) \
- template <BOOST_PP_ENUM_PARAMS(n, class P)> \
- struct sequence< \
- BOOST_PP_ENUM_PARAMS(n, P) \
- BOOST_PP_COMMA_IF(n) \
- BOOST_PP_ENUM( \
- BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE, n), \
- boost::mpl::na BOOST_PP_TUPLE_EAT(3), \
- ~ \
- ) \
- > : impl::BOOST_PP_CAT(sequence, n)<BOOST_PP_ENUM_PARAMS(n, P)> \
- {};
-
- BOOST_PP_REPEAT_FROM_TO(
- 1,
- BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
- BOOST_METAPARSE_SEQUENCE_N,
- ~
- )
-
- #undef BOOST_METAPARSE_SEQUENCE_N
- }
- }
-}
+#if BOOST_METAPARSE_STD >= 2011
+# include <boost/metaparse/v1/cpp11/sequence.hpp>
+#else
+# include <boost/metaparse/v1/cpp98/sequence.hpp>
+#endif
#endif
diff --git a/boost/move/algo/adaptive_sort.hpp b/boost/move/algo/adaptive_sort.hpp
index 581939937c..cdffa2e989 100644
--- a/boost/move/algo/adaptive_sort.hpp
+++ b/boost/move/algo/adaptive_sort.hpp
@@ -180,7 +180,7 @@ void adaptive_sort_combine_blocks
size_type const max_i = n_reg_combined + (l_irreg_combined != 0);
if(merge_left || !use_buf) {
- for( size_type combined_i = 0; combined_i != max_i; ++combined_i, combined_first += l_reg_combined) {
+ for( size_type combined_i = 0; combined_i != max_i; ) {
//Now merge blocks
bool const is_last = combined_i==n_reg_combined;
size_type const l_cur_combined = is_last ? l_irreg_combined : l_reg_combined;
@@ -202,11 +202,15 @@ void adaptive_sort_combine_blocks
(keys, key_comp, combined_first, l_block, 0u, n_block_a, n_block_b, l_irreg2, comp, xbuf_used);
}
BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" After merge_blocks_L: ", len + l_block);
+ ++combined_i;
+ if(combined_i != max_i)
+ combined_first += l_reg_combined;
}
}
else{
combined_first += l_reg_combined*(max_i-1);
- for( size_type combined_i = max_i; combined_i--; combined_first -= l_reg_combined) {
+ for( size_type combined_i = max_i; combined_i; ) {
+ --combined_i;
bool const is_last = combined_i==n_reg_combined;
size_type const l_cur_combined = is_last ? l_irreg_combined : l_reg_combined;
@@ -222,6 +226,8 @@ void adaptive_sort_combine_blocks
merge_blocks_right
(keys, key_comp, combined_first, l_block, n_block_a, n_block_b, l_irreg2, comp, xbuf_used);
BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" After merge_blocks_R: ", len + l_block);
+ if(combined_i)
+ combined_first -= l_reg_combined;
}
}
}
diff --git a/boost/move/algo/detail/set_difference.hpp b/boost/move/algo/detail/set_difference.hpp
index 51d047592a..c988294d3b 100644
--- a/boost/move/algo/detail/set_difference.hpp
+++ b/boost/move/algo/detail/set_difference.hpp
@@ -174,7 +174,7 @@ ForwardOutputIt1 inplace_set_unique_difference
++first2;
}
else if (comp(*first1, *first2)){
- //skip any adjacent equivalent elementin range 1
+ //skip any adjacent equivalent element in range 1
ForwardOutputIt1 result = first1;
if (++first1 != last1 && !comp(*result, *first1)) {
//Some elements from range 1 must be skipped, no longer an inplace operation
diff --git a/boost/mp11/detail/config.hpp b/boost/mp11/detail/config.hpp
index 63c21f43f4..248dce0a9f 100644
--- a/boost/mp11/detail/config.hpp
+++ b/boost/mp11/detail/config.hpp
@@ -127,19 +127,11 @@
# define BOOST_MP11_DEPRECATED(msg)
#elif BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 50000 )
# define BOOST_MP11_DEPRECATED(msg) __attribute__((deprecated(msg)))
-#elif BOOST_MP11_CLANG
-# if defined(__has_cpp_attribute)
-// 3.8 warns about [[deprecated]] when in C++11 mode
-// so we only use it on 3.9 and above, detected via [[fallthrough]]
-// can't version check because Apple
-# if __has_cpp_attribute(deprecated) && __has_cpp_attribute(fallthrough)
-# define BOOST_MP11_DEPRECATED(msg) [[deprecated(msg)]]
-# else
-# define BOOST_MP11_DEPRECATED(msg)
-# endif
-# else // defined(__has_cpp_attribute)
+#elif BOOST_MP11_WORKAROUND( BOOST_MP11_CLANG, < 304 )
# define BOOST_MP11_DEPRECATED(msg)
-# endif
+#elif BOOST_MP11_CLANG
+// -pedantic warns about [[deprecated]] when in C++11 mode
+# define BOOST_MP11_DEPRECATED(msg) __attribute__((deprecated(msg)))
#else
# define BOOST_MP11_DEPRECATED(msg) [[deprecated(msg)]]
#endif
diff --git a/boost/mp11/detail/mp_count.hpp b/boost/mp11/detail/mp_count.hpp
index 2daed904c6..1e221ca355 100644
--- a/boost/mp11/detail/mp_count.hpp
+++ b/boost/mp11/detail/mp_count.hpp
@@ -39,13 +39,13 @@ constexpr std::size_t cx_plus()
template<class T1, class... T> constexpr std::size_t cx_plus(T1 t1, T... t)
{
- return t1 + cx_plus(t...);
+ return static_cast<std::size_t>(t1) + cx_plus(t...);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T>
constexpr std::size_t cx_plus(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T... t)
{
- return t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 + t9 + t10 + cx_plus(t...);
+ return static_cast<std::size_t>(t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 + t9 + t10) + cx_plus(t...);
}
template<template<class...> class L, class... T, class V> struct mp_count_impl<L<T...>, V>
diff --git a/boost/mp11/function.hpp b/boost/mp11/function.hpp
index f1c11b4987..8e1114a117 100644
--- a/boost/mp11/function.hpp
+++ b/boost/mp11/function.hpp
@@ -80,7 +80,8 @@ template<class... T> using mp_and = typename detail::mp_and_impl<mp_list<T...>>:
#endif
// mp_all<T...>
-#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 100000 )
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86355
+#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, != 0 )
template<class... T> using mp_all = mp_bool< mp_count_if< mp_list<T...>, mp_not >::value == 0 >;
@@ -125,7 +126,8 @@ template<class T1, class... T> struct mp_or_impl<T1, T...>
} // namespace detail
// mp_any<T...>
-#if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 100000 ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86356
+#if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, != 0 ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
template<class... T> using mp_any = mp_bool<(static_cast<bool>(T::value) || ...)>;
diff --git a/boost/mp11/version.hpp b/boost/mp11/version.hpp
index 5a1f21a50e..092b329301 100644
--- a/boost/mp11/version.hpp
+++ b/boost/mp11/version.hpp
@@ -11,6 +11,6 @@
// Same format as BOOST_VERSION:
// major * 100000 + minor * 100 + patch
-#define BOOST_MP11_VERSION 107000
+#define BOOST_MP11_VERSION 107100
#endif // #ifndef BOOST_MP11_VERSION_HPP_INCLUDED
diff --git a/boost/mpi/collectives/all_gather.hpp b/boost/mpi/collectives/all_gather.hpp
index 4adaeb9c87..cf75f329fc 100644
--- a/boost/mpi/collectives/all_gather.hpp
+++ b/boost/mpi/collectives/all_gather.hpp
@@ -57,8 +57,8 @@ all_gather_impl(const communicator& comm, const T* in_values, int n,
std::vector<int> oasizes(nproc);
int oasize = oa.size();
BOOST_MPI_CHECK_RESULT(MPI_Allgather,
- (&oasize, 1, MPI_INTEGER,
- c_data(oasizes), 1, MPI_INTEGER,
+ (&oasize, 1, MPI_INT,
+ c_data(oasizes), 1, MPI_INT,
MPI_Comm(comm)));
// Gather the archives, which can be of different sizes, so
// we need to use allgatherv.
diff --git a/boost/mpi/collectives/gather.hpp b/boost/mpi/collectives/gather.hpp
index 386bfdd1a1..34f37997ba 100644
--- a/boost/mpi/collectives/gather.hpp
+++ b/boost/mpi/collectives/gather.hpp
@@ -69,8 +69,8 @@ gather_impl(const communicator& comm, const T* in_values, int n, T* out_values,
std::vector<int> oasizes(is_root ? nproc : 0);
int oasize = oa.size();
BOOST_MPI_CHECK_RESULT(MPI_Gather,
- (&oasize, 1, MPI_INTEGER,
- c_data(oasizes), 1, MPI_INTEGER,
+ (&oasize, 1, MPI_INT,
+ c_data(oasizes), 1, MPI_INT,
root, MPI_Comm(comm)));
// Gather the archives, which can be of different sizes, so
// we need to use gatherv.
diff --git a/boost/mpi/collectives/scatter.hpp b/boost/mpi/collectives/scatter.hpp
index 0c91b1e6aa..ae3adcbcfa 100644
--- a/boost/mpi/collectives/scatter.hpp
+++ b/boost/mpi/collectives/scatter.hpp
@@ -100,8 +100,8 @@ dispatch_scatter_sendbuf(const communicator& comm,
// Distribute the sizes
int myarchsize;
BOOST_MPI_CHECK_RESULT(MPI_Scatter,
- (non_const_data(archsizes), 1, MPI_INTEGER,
- &myarchsize, 1, MPI_INTEGER, root, comm));
+ (non_const_data(archsizes), 1, MPI_INT,
+ &myarchsize, 1, MPI_INT, root, comm));
std::vector<int> offsets;
if (root == comm.rank()) {
sizes2offsets(archsizes, offsets);
diff --git a/boost/mpi/communicator.hpp b/boost/mpi/communicator.hpp
index 6e55b167f9..ff889d00a3 100644
--- a/boost/mpi/communicator.hpp
+++ b/boost/mpi/communicator.hpp
@@ -34,9 +34,6 @@
// For (de-)serializing skeletons and content
#include <boost/mpi/skeleton_and_content_fwd.hpp>
-// For (de-)serializing arrays
-#include <boost/serialization/array.hpp>
-
#include <boost/mpi/detail/point_to_point.hpp>
#include <boost/mpi/status.hpp>
#include <boost/mpi/request.hpp>
@@ -802,23 +799,7 @@ class BOOST_MPI_DECL communicator
* Split the communicator into multiple, disjoint communicators
* each of which is based on a particular color. This is a
* collective operation that returns a new communicator that is a
- * subgroup of @p this. This routine is functionally equivalent to
- * @c MPI_Comm_split.
- *
- * @param color The color of this process. All processes with the
- * same @p color value will be placed into the same group.
- *
- * @returns A new communicator containing all of the processes in
- * @p this that have the same @p color.
- */
- communicator split(int color) const;
-
- /**
- * Split the communicator into multiple, disjoint communicators
- * each of which is based on a particular color. This is a
- * collective operation that returns a new communicator that is a
- * subgroup of @p this. This routine is functionally equivalent to
- * @c MPI_Comm_split.
+ * subgroup of @p this.
*
* @param color The color of this process. All processes with the
* same @p color value will be placed into the same group.
@@ -833,6 +814,7 @@ class BOOST_MPI_DECL communicator
* @p this that have the same @p color.
*/
communicator split(int color, int key) const;
+ communicator split(int color) const;
/**
* Determine if the communicator is in fact an intercommunicator
@@ -1157,11 +1139,15 @@ inline bool operator!=(const communicator& comm1, const communicator& comm2)
return !(comm1 == comm2);
}
+}} // boost::mpi
/************************************************************************
* Implementation details *
************************************************************************/
+#include <boost/mpi/detail/request_handlers.hpp>
+
+namespace boost { namespace mpi {
/**
* INTERNAL ONLY (using the same 'end' name might be considerd unfortunate
*/
@@ -1308,6 +1294,7 @@ template<typename T>
void
communicator::send_impl(int dest, int tag, const T& value, mpl::true_) const
{
+ // received by recv or trivial handler.
BOOST_MPI_CHECK_RESULT(MPI_Send,
(const_cast<T*>(&value), 1, get_mpi_datatype<T>(value),
dest, tag, MPI_Comm(*this)));
@@ -1355,26 +1342,37 @@ communicator::array_send_impl(int dest, int tag, const T* values, int n,
mpl::false_) const
{
packed_oarchive oa(*this);
- oa << n << boost::serialization::make_array(values, n);
+ T const* v = values;
+ while (v < values+n) {
+ oa << *v++;
+ }
send(dest, tag, oa);
}
template<typename T, typename A>
void communicator::send_vector(int dest, int tag,
- const std::vector<T,A>& value, mpl::true_ true_type) const
+ const std::vector<T,A>& values, mpl::true_ primitive) const
{
- // send the vector size
- typename std::vector<T,A>::size_type size = value.size();
- send(dest, tag, size);
- // send the data
- this->array_send_impl(dest, tag, value.data(), size, true_type);
+#if defined(BOOST_MPI_USE_IMPROBE)
+ array_send_impl(dest, tag, values.data(), values.size(), primitive);
+#else
+ {
+ // non blocking recv by legacy_dynamic_primitive_array_handler
+ // blocking recv by recv_vector(source,tag,value,primitive)
+ // send the vector size
+ typename std::vector<T,A>::size_type size = values.size();
+ send(dest, tag, size);
+ // send the data
+ this->array_send_impl(dest, tag, values.data(), size, primitive);
+ }
+#endif
}
template<typename T, typename A>
void communicator::send_vector(int dest, int tag,
- const std::vector<T,A>& value, mpl::false_ false_type) const
+ const std::vector<T,A>& value, mpl::false_ primitive) const
{
- this->send_impl(dest, tag, value, false_type);
+ this->send_impl(dest, tag, value, primitive);
}
template<typename T, typename A>
@@ -1396,7 +1394,6 @@ template<typename T>
status communicator::recv_impl(int source, int tag, T& value, mpl::true_) const
{
status stat;
-
BOOST_MPI_CHECK_RESULT(MPI_Recv,
(const_cast<T*>(&value), 1,
get_mpi_datatype<T>(value),
@@ -1444,38 +1441,42 @@ status
communicator::array_recv_impl(int source, int tag, T* values, int n,
mpl::false_) const
{
- // Receive the message
packed_iarchive ia(*this);
status stat = recv(source, tag, ia);
-
- // Determine how much data we are going to receive
- int count;
- ia >> count;
-
- // Deserialize the data in the message
- boost::serialization::array_wrapper<T> arr(values, count > n? n : count);
- ia >> arr;
-
- if (count > n) {
- boost::throw_exception(
- std::range_error("communicator::recv: message receive overflow"));
+ T* v = values;
+ while (v != values+n) {
+ ia >> *v++;
}
-
- stat.m_count = count;
+ stat.m_count = n;
return stat;
}
template<typename T, typename A>
status communicator::recv_vector(int source, int tag,
- std::vector<T,A>& value, mpl::true_ true_type) const
+ std::vector<T,A>& values, mpl::true_ primitive) const
{
- // receive the vector size
- typename std::vector<T,A>::size_type size = 0;
- recv(source, tag, size);
- // size the vector
- value.resize(size);
- // receive the data
- return this->array_recv_impl(source, tag, value.data(), size, true_type);
+#if defined(BOOST_MPI_USE_IMPROBE)
+ {
+ MPI_Message msg;
+ status stat;
+ BOOST_MPI_CHECK_RESULT(MPI_Mprobe, (source,tag,*this,&msg,&stat.m_status));
+ int count;
+ BOOST_MPI_CHECK_RESULT(MPI_Get_count, (&stat.m_status,get_mpi_datatype<T>(),&count));
+ values.resize(count);
+ BOOST_MPI_CHECK_RESULT(MPI_Mrecv, (values.data(), count, get_mpi_datatype<T>(), &msg, &stat.m_status));
+ return stat;
+ }
+#else
+ {
+ // receive the vector size
+ typename std::vector<T,A>::size_type size = 0;
+ recv(source, tag, size);
+ // size the vector
+ values.resize(size);
+ // receive the data
+ return this->array_recv_impl(source, tag, values.data(), size, primitive);
+ }
+#endif
}
template<typename T, typename A>
@@ -1542,12 +1543,7 @@ template<typename T>
request
communicator::isend_impl(int dest, int tag, const T& value, mpl::true_) const
{
- request req;
- BOOST_MPI_CHECK_RESULT(MPI_Isend,
- (const_cast<T*>(&value), 1,
- get_mpi_datatype<T>(value),
- dest, tag, MPI_Comm(*this), &req.m_requests[0]));
- return req;
+ return request::make_trivial_send(*this, dest, tag, value);
}
// We're sending a type that does not have an associated MPI
@@ -1560,7 +1556,7 @@ communicator::isend_impl(int dest, int tag, const T& value, mpl::false_) const
shared_ptr<packed_oarchive> archive(new packed_oarchive(*this));
*archive << value;
request result = isend(dest, tag, *archive);
- result.m_data = archive;
+ result.preserve(archive);
return result;
}
@@ -1581,16 +1577,9 @@ request communicator::isend(int dest, int tag, const std::vector<T,A>& values) c
template<typename T, class A>
request
communicator::isend_vector(int dest, int tag, const std::vector<T,A>& values,
- mpl::true_) const
+ mpl::true_ primitive) const
{
- std::size_t size = values.size();
- request req = this->isend_impl(dest, tag, size, mpl::true_());
- BOOST_MPI_CHECK_RESULT(MPI_Isend,
- (const_cast<T*>(values.data()), size,
- get_mpi_datatype<T>(),
- dest, tag, MPI_Comm(*this), &req.m_requests[1]));
- return req;
-
+ return request::make_dynamic_primitive_array_send(*this, dest, tag, values);
}
template<typename T, class A>
@@ -1606,12 +1595,7 @@ request
communicator::array_isend_impl(int dest, int tag, const T* values, int n,
mpl::true_) const
{
- request req;
- BOOST_MPI_CHECK_RESULT(MPI_Isend,
- (const_cast<T*>(values), n,
- get_mpi_datatype<T>(*values),
- dest, tag, MPI_Comm(*this), &req.m_requests[0]));
- return req;
+ return request::make_trivial_send(*this, dest, tag, values, n);
}
template<typename T>
@@ -1620,9 +1604,12 @@ communicator::array_isend_impl(int dest, int tag, const T* values, int n,
mpl::false_) const
{
shared_ptr<packed_oarchive> archive(new packed_oarchive(*this));
- *archive << n << boost::serialization::make_array(values, n);
+ T const* v = values;
+ while (v < values+n) {
+ *archive << *v++;
+ }
request result = isend(dest, tag, *archive);
- result.m_data = archive;
+ result.preserve(archive);
return result;
}
@@ -1634,323 +1621,20 @@ request communicator::isend(int dest, int tag, const T* values, int n) const
return array_isend_impl(dest, tag, values, n, is_mpi_datatype<T>());
}
-namespace detail {
- /**
- * Internal data structure that stores everything required to manage
- * the receipt of serialized data via a request object.
- */
- template<typename T>
- struct serialized_irecv_data
- {
- serialized_irecv_data(const communicator& comm, int source, int tag,
- T& value)
- : comm(comm), source(source), tag(tag), ia(comm), value(value)
- {
- }
-
- void deserialize(status& stat)
- {
- ia >> value;
- stat.m_count = 1;
- }
-
- communicator comm;
- int source;
- int tag;
- std::size_t count;
- packed_iarchive ia;
- T& value;
- };
-
- template<>
- struct serialized_irecv_data<packed_iarchive>
- {
- serialized_irecv_data(const communicator& comm, int source, int tag,
- packed_iarchive& ia)
- : comm(comm), source(source), tag(tag), ia(ia) { }
-
- void deserialize(status&) { /* Do nothing. */ }
-
- communicator comm;
- int source;
- int tag;
- std::size_t count;
- packed_iarchive& ia;
- };
-
- /**
- * Internal data structure that stores everything required to manage
- * the receipt of an array of serialized data via a request object.
- */
- template<typename T>
- struct serialized_array_irecv_data
- {
- serialized_array_irecv_data(const communicator& comm, int source, int tag,
- T* values, int n)
- : comm(comm), source(source), tag(tag), ia(comm), values(values), n(n)
- {
- }
-
- void deserialize(status& stat);
-
- communicator comm;
- int source;
- int tag;
- std::size_t count;
- packed_iarchive ia;
- T* values;
- int n;
- };
-
- template<typename T>
- void serialized_array_irecv_data<T>::deserialize(status& stat)
- {
- // Determine how much data we are going to receive
- int count;
- ia >> count;
-
- // Deserialize the data in the message
- boost::serialization::array_wrapper<T> arr(values, count > n? n : count);
- ia >> arr;
-
- if (count > n) {
- boost::throw_exception(
- std::range_error("communicator::recv: message receive overflow"));
- }
-
- stat.m_count = count;
- }
-
- /**
- * Internal data structure that stores everything required to manage
- * the receipt of an array of primitive data but unknown size.
- * Such an array can have been send with blocking operation and so must
- * be compatible with the (size_t,raw_data[]) format.
- */
- template<typename T, class A>
- struct dynamic_array_irecv_data
- {
- BOOST_STATIC_ASSERT_MSG(is_mpi_datatype<T>::value, "Can only be specialized for MPI datatypes.");
-
- dynamic_array_irecv_data(const communicator& comm, int source, int tag,
- std::vector<T,A>& values)
- : comm(comm), source(source), tag(tag), count(-1), values(values)
- {
- }
-
- communicator comm;
- int source;
- int tag;
- std::size_t count;
- std::vector<T,A>& values;
- };
-
-}
-
-template<typename T>
-optional<status>
-request::handle_serialized_irecv(request* self, request_action action)
-{
- typedef detail::serialized_irecv_data<T> data_t;
- shared_ptr<data_t> data = static_pointer_cast<data_t>(self->m_data);
-
- if (action == ra_wait) {
- status stat;
- if (self->m_requests[1] == MPI_REQUEST_NULL) {
- // Wait for the count message to complete
- BOOST_MPI_CHECK_RESULT(MPI_Wait,
- (self->m_requests, &stat.m_status));
- // Resize our buffer and get ready to receive its data
- data->ia.resize(data->count);
- BOOST_MPI_CHECK_RESULT(MPI_Irecv,
- (data->ia.address(), data->ia.size(), MPI_PACKED,
- stat.source(), stat.tag(),
- MPI_Comm(data->comm), self->m_requests + 1));
- }
-
- // Wait until we have received the entire message
- BOOST_MPI_CHECK_RESULT(MPI_Wait,
- (self->m_requests + 1, &stat.m_status));
-
- data->deserialize(stat);
- return stat;
- } else if (action == ra_test) {
- status stat;
- int flag = 0;
-
- if (self->m_requests[1] == MPI_REQUEST_NULL) {
- // Check if the count message has completed
- BOOST_MPI_CHECK_RESULT(MPI_Test,
- (self->m_requests, &flag, &stat.m_status));
- if (flag) {
- // Resize our buffer and get ready to receive its data
- data->ia.resize(data->count);
- BOOST_MPI_CHECK_RESULT(MPI_Irecv,
- (data->ia.address(), data->ia.size(),MPI_PACKED,
- stat.source(), stat.tag(),
- MPI_Comm(data->comm), self->m_requests + 1));
- } else
- return optional<status>(); // We have not finished yet
- }
-
- // Check if we have received the message data
- BOOST_MPI_CHECK_RESULT(MPI_Test,
- (self->m_requests + 1, &flag, &stat.m_status));
- if (flag) {
- data->deserialize(stat);
- return stat;
- } else
- return optional<status>();
- } else {
- return optional<status>();
- }
-}
-
-template<typename T>
-optional<status>
-request::handle_serialized_array_irecv(request* self, request_action action)
-{
- typedef detail::serialized_array_irecv_data<T> data_t;
- shared_ptr<data_t> data = static_pointer_cast<data_t>(self->m_data);
-
- if (action == ra_wait) {
- status stat;
- if (self->m_requests[1] == MPI_REQUEST_NULL) {
- // Wait for the count message to complete
- BOOST_MPI_CHECK_RESULT(MPI_Wait,
- (self->m_requests, &stat.m_status));
- // Resize our buffer and get ready to receive its data
- data->ia.resize(data->count);
- BOOST_MPI_CHECK_RESULT(MPI_Irecv,
- (data->ia.address(), data->ia.size(), MPI_PACKED,
- stat.source(), stat.tag(),
- MPI_Comm(data->comm), self->m_requests + 1));
- }
-
- // Wait until we have received the entire message
- BOOST_MPI_CHECK_RESULT(MPI_Wait,
- (self->m_requests + 1, &stat.m_status));
-
- data->deserialize(stat);
- return stat;
- } else if (action == ra_test) {
- status stat;
- int flag = 0;
-
- if (self->m_requests[1] == MPI_REQUEST_NULL) {
- // Check if the count message has completed
- BOOST_MPI_CHECK_RESULT(MPI_Test,
- (self->m_requests, &flag, &stat.m_status));
- if (flag) {
- // Resize our buffer and get ready to receive its data
- data->ia.resize(data->count);
- BOOST_MPI_CHECK_RESULT(MPI_Irecv,
- (data->ia.address(), data->ia.size(),MPI_PACKED,
- stat.source(), stat.tag(),
- MPI_Comm(data->comm), self->m_requests + 1));
- } else
- return optional<status>(); // We have not finished yet
- }
-
- // Check if we have received the message data
- BOOST_MPI_CHECK_RESULT(MPI_Test,
- (self->m_requests + 1, &flag, &stat.m_status));
- if (flag) {
- data->deserialize(stat);
- return stat;
- } else
- return optional<status>();
- } else {
- return optional<status>();
- }
-}
-
-template<typename T, class A>
-optional<status>
-request::handle_dynamic_primitive_array_irecv(request* self, request_action action)
-{
- typedef detail::dynamic_array_irecv_data<T,A> data_t;
- shared_ptr<data_t> data = static_pointer_cast<data_t>(self->m_data);
-
- if (action == ra_wait) {
- status stat;
- if (self->m_requests[1] == MPI_REQUEST_NULL) {
- // Wait for the count message to complete
- BOOST_MPI_CHECK_RESULT(MPI_Wait,
- (self->m_requests, &stat.m_status));
- // Resize our buffer and get ready to receive its data
- data->values.resize(data->count);
- BOOST_MPI_CHECK_RESULT(MPI_Irecv,
- (&(data->values[0]), data->values.size(), get_mpi_datatype<T>(),
- stat.source(), stat.tag(),
- MPI_Comm(data->comm), self->m_requests + 1));
- }
-
- // Wait until we have received the entire message
- BOOST_MPI_CHECK_RESULT(MPI_Wait,
- (self->m_requests + 1, &stat.m_status));
- return stat;
- } else if (action == ra_test) {
- status stat;
- int flag = 0;
-
- if (self->m_requests[1] == MPI_REQUEST_NULL) {
- // Check if the count message has completed
- BOOST_MPI_CHECK_RESULT(MPI_Test,
- (self->m_requests, &flag, &stat.m_status));
- if (flag) {
- // Resize our buffer and get ready to receive its data
- data->values.resize(data->count);
- BOOST_MPI_CHECK_RESULT(MPI_Irecv,
- (&(data->values[0]), data->values.size(),MPI_PACKED,
- stat.source(), stat.tag(),
- MPI_Comm(data->comm), self->m_requests + 1));
- } else
- return optional<status>(); // We have not finished yet
- }
-
- // Check if we have received the message data
- BOOST_MPI_CHECK_RESULT(MPI_Test,
- (self->m_requests + 1, &flag, &stat.m_status));
- if (flag) {
- return stat;
- } else
- return optional<status>();
- } else {
- return optional<status>();
- }
-}
-
// We're receiving a type that has an associated MPI datatype, so we
// map directly to that datatype.
template<typename T>
request
communicator::irecv_impl(int source, int tag, T& value, mpl::true_) const
{
- request req;
- BOOST_MPI_CHECK_RESULT(MPI_Irecv,
- (const_cast<T*>(&value), 1,
- get_mpi_datatype<T>(value),
- source, tag, MPI_Comm(*this), &req.m_requests[0]));
- return req;
+ return request::make_trivial_recv(*this, source, tag, value);
}
template<typename T>
request
communicator::irecv_impl(int source, int tag, T& value, mpl::false_) const
{
- typedef detail::serialized_irecv_data<T> data_t;
- shared_ptr<data_t> data(new data_t(*this, source, tag, value));
- request req;
- req.m_data = data;
- req.m_handler = request::handle_serialized_irecv<T>;
-
- BOOST_MPI_CHECK_RESULT(MPI_Irecv,
- (&data->count, 1,
- get_mpi_datatype<std::size_t>(data->count),
- source, tag, MPI_Comm(*this), &req.m_requests[0]));
-
- return req;
+ return request::make_serialized(*this, source, tag, value);
}
template<typename T>
@@ -1965,12 +1649,7 @@ request
communicator::array_irecv_impl(int source, int tag, T* values, int n,
mpl::true_) const
{
- request req;
- BOOST_MPI_CHECK_RESULT(MPI_Irecv,
- (const_cast<T*>(values), n,
- get_mpi_datatype<T>(*values),
- source, tag, MPI_Comm(*this), &req.m_requests[0]));
- return req;
+ return request::make_trivial_recv(*this, source, tag, values, n);
}
template<typename T>
@@ -1978,37 +1657,15 @@ request
communicator::array_irecv_impl(int source, int tag, T* values, int n,
mpl::false_) const
{
- typedef detail::serialized_array_irecv_data<T> data_t;
- shared_ptr<data_t> data(new data_t(*this, source, tag, values, n));
- request req;
- req.m_data = data;
- req.m_handler = request::handle_serialized_array_irecv<T>;
-
- BOOST_MPI_CHECK_RESULT(MPI_Irecv,
- (&data->count, 1,
- get_mpi_datatype<std::size_t>(data->count),
- source, tag, MPI_Comm(*this), &req.m_requests[0]));
-
- return req;
+ return request::make_serialized_array(*this, source, tag, values, n);
}
template<typename T, class A>
request
communicator::irecv_vector(int source, int tag, std::vector<T,A>& values,
- mpl::true_) const
+ mpl::true_ primitive) const
{
- typedef detail::dynamic_array_irecv_data<T,A> data_t;
- shared_ptr<data_t> data(new data_t(*this, source, tag, values));
- request req;
- req.m_data = data;
- req.m_handler = request::handle_dynamic_primitive_array_irecv<T,A>;
-
- BOOST_MPI_CHECK_RESULT(MPI_Irecv,
- (&data->count, 1,
- get_mpi_datatype<std::size_t>(data->count),
- source, tag, MPI_Comm(*this), &req.m_requests[0]));
-
- return req;
+ return request::make_dynamic_primitive_array_recv(*this, source, tag, values);
}
template<typename T, class A>
diff --git a/boost/mpi/config.hpp b/boost/mpi/config.hpp
index c83277f66b..48c0a9fe29 100644
--- a/boost/mpi/config.hpp
+++ b/boost/mpi/config.hpp
@@ -32,9 +32,33 @@
*/
#define BOOST_MPI_HOMOGENEOUS
+#if defined MPI_VERSION
+/** @brief Major version of the underlying MPI implementation supproted standard.
+ *
+ * If, for some reason, MPI_VERSION is not supported, you should probably set that
+ * according to your MPI documentation
+ */
+# define BOOST_MPI_VERSION MPI_VERSION
+#else
+// assume a safe default
+# define BOOST_MPI_VERSION 2
+#endif
+
+#if defined MPI_SUBVERSION
+/** @brief Major version of the underlying MPI implementation supproted standard.
+ *
+ * If, for some reason, MPI_SUBVERSION is not supported, you should probably set that
+ * according to your MPI documentation
+ */
+# define BOOST_MPI_SUBVERSION MPI_SUBVERSION
+#else
+// assume a safe default
+# define BOOST_MPI_SUBVERSION 2
+#endif
+
// If this is an MPI-2 implementation, define configuration macros for
// the features we are interested in.
-#if defined(MPI_VERSION) && MPI_VERSION >= 2
+#if BOOST_MPI_VERSION >= 2
/** @brief Determine if the MPI implementation has support for memory
* allocation.
*
@@ -96,6 +120,11 @@
// Configuration for MPICH
#endif
+#if BOOST_MPI_VERSION >= 3 && (!defined(I_MPI_NUMVERSION))
+// This is intel
+#define BOOST_MPI_USE_IMPROBE 1
+#endif
+
/*****************************************************************************
* *
* DLL import/export options *
diff --git a/boost/mpi/datatype.hpp b/boost/mpi/datatype.hpp
index 1f069977d0..b50662229a 100644
--- a/boost/mpi/datatype.hpp
+++ b/boost/mpi/datatype.hpp
@@ -280,16 +280,16 @@ struct is_mpi_datatype<std::array<T, N> >
// Define wchar_t specialization of is_mpi_datatype, if possible.
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) && \
- (defined(MPI_WCHAR) || (defined(MPI_VERSION) && MPI_VERSION >= 2))
+ (defined(MPI_WCHAR) || (BOOST_MPI_VERSION >= 2))
BOOST_MPI_DATATYPE(wchar_t, MPI_WCHAR, builtin);
#endif
// Define long long or __int64 specialization of is_mpi_datatype, if possible.
#if defined(BOOST_HAS_LONG_LONG) && \
- (defined(MPI_LONG_LONG_INT) || (defined(MPI_VERSION) && MPI_VERSION >= 2))
+ (defined(MPI_LONG_LONG_INT) || (BOOST_MPI_VERSION >= 2))
BOOST_MPI_DATATYPE(long long, MPI_LONG_LONG_INT, builtin);
#elif defined(BOOST_HAS_MS_INT64) && \
- (defined(MPI_LONG_LONG_INT) || (defined(MPI_VERSION) && MPI_VERSION >= 2))
+ (defined(MPI_LONG_LONG_INT) || (BOOST_MPI_VERSION >= 2))
BOOST_MPI_DATATYPE(__int64, MPI_LONG_LONG_INT, builtin);
#endif
@@ -300,16 +300,16 @@ BOOST_MPI_DATATYPE(__int64, MPI_LONG_LONG_INT, builtin);
// MPI_UNSIGNED_LONG_LONG.
#if defined(BOOST_HAS_LONG_LONG) && \
(defined(MPI_UNSIGNED_LONG_LONG) \
- || (defined(MPI_VERSION) && MPI_VERSION >= 2))
+ || (BOOST_MPI_VERSION >= 2))
BOOST_MPI_DATATYPE(unsigned long long, MPI_UNSIGNED_LONG_LONG, builtin);
#elif defined(BOOST_HAS_MS_INT64) && \
(defined(MPI_UNSIGNED_LONG_LONG) \
- || (defined(MPI_VERSION) && MPI_VERSION >= 2))
+ || (BOOST_MPI_VERSION >= 2))
BOOST_MPI_DATATYPE(unsigned __int64, MPI_UNSIGNED_LONG_LONG, builtin);
#endif
// Define signed char specialization of is_mpi_datatype, if possible.
-#if defined(MPI_SIGNED_CHAR) || (defined(MPI_VERSION) && MPI_VERSION >= 2)
+#if defined(MPI_SIGNED_CHAR) || (BOOST_MPI_VERSION >= 2)
BOOST_MPI_DATATYPE(signed char, MPI_SIGNED_CHAR, builtin);
#endif
diff --git a/boost/mpi/detail/antiques.hpp b/boost/mpi/detail/antiques.hpp
index 0bd235b2c1..a84760f8f1 100644
--- a/boost/mpi/detail/antiques.hpp
+++ b/boost/mpi/detail/antiques.hpp
@@ -19,10 +19,10 @@ namespace detail {
// serve as an incentive to get rid of this when those compilers
// are dropped.
template <typename T, typename A>
- T* c_data(std::vector<T,A>& v) { return &(v[0]); }
+ T* c_data(std::vector<T,A>& v) { return v.empty() ? static_cast<T*>(0) : &(v[0]); }
template <typename T, typename A>
- T const* c_data(std::vector<T,A> const& v) { return &(v[0]); }
+ T const* c_data(std::vector<T,A> const& v) { return v.empty() ? static_cast<T const*>(0) : &(v[0]); }
// Some old MPI implementation (OpenMPI 1.6 for example) have non
// conforming API w.r.t. constness.
diff --git a/boost/mpi/detail/broadcast_sc.hpp b/boost/mpi/detail/broadcast_sc.hpp
index c84da662a2..51a8dff62d 100644
--- a/boost/mpi/detail/broadcast_sc.hpp
+++ b/boost/mpi/detail/broadcast_sc.hpp
@@ -14,14 +14,6 @@
namespace boost { namespace mpi {
template<typename T>
-inline void
-broadcast(const communicator& comm, skeleton_proxy<T>& proxy, int root)
-{
- const skeleton_proxy<T>& const_proxy(proxy);
- broadcast(comm, const_proxy, root);
-}
-
-template<typename T>
void
broadcast(const communicator& comm, const skeleton_proxy<T>& proxy, int root)
{
@@ -36,6 +28,15 @@ broadcast(const communicator& comm, const skeleton_proxy<T>& proxy, int root)
}
}
+template<typename T>
+inline void
+broadcast(const communicator& comm, skeleton_proxy<T>& proxy, int root)
+{
+ const skeleton_proxy<T>& const_proxy(proxy);
+ broadcast(comm, const_proxy, root);
+}
+
+
} } // end namespace boost::mpi
#endif // BOOST_MPI_BROADCAST_SC_HPP
diff --git a/boost/mpi/detail/communicator_sc.hpp b/boost/mpi/detail/communicator_sc.hpp
index 1dfcc3c52d..83fa3a3e39 100644
--- a/boost/mpi/detail/communicator_sc.hpp
+++ b/boost/mpi/detail/communicator_sc.hpp
@@ -50,46 +50,10 @@ communicator::isend(int dest, int tag, const skeleton_proxy<T>& proxy) const
*archive << proxy.object;
request result = isend(dest, tag, *archive);
- result.m_data = archive;
+ result.preserve(archive);
return result;
}
-namespace detail {
- template<typename T>
- struct serialized_irecv_data<const skeleton_proxy<T> >
- {
- serialized_irecv_data(const communicator& comm, int source, int tag,
- skeleton_proxy<T> proxy)
- : comm(comm), source(source), tag(tag), isa(comm),
- ia(isa.get_skeleton()), proxy(proxy) { }
-
- void deserialize(status& stat)
- {
- isa >> proxy.object;
- stat.m_count = 1;
- }
-
- communicator comm;
- int source;
- int tag;
- std::size_t count;
- packed_skeleton_iarchive isa;
- packed_iarchive& ia;
- skeleton_proxy<T> proxy;
- };
-
- template<typename T>
- struct serialized_irecv_data<skeleton_proxy<T> >
- : public serialized_irecv_data<const skeleton_proxy<T> >
- {
- typedef serialized_irecv_data<const skeleton_proxy<T> > inherited;
-
- serialized_irecv_data(const communicator& comm, int source, int tag,
- const skeleton_proxy<T>& proxy)
- : inherited(comm, source, tag, proxy) { }
- };
-}
-
} } // end namespace boost::mpi
#endif // BOOST_MPI_COMMUNICATOR_SC_HPP
diff --git a/boost/mpi/detail/mpi_datatype_primitive.hpp b/boost/mpi/detail/mpi_datatype_primitive.hpp
index 6a82624e43..fc05d78612 100644
--- a/boost/mpi/detail/mpi_datatype_primitive.hpp
+++ b/boost/mpi/detail/mpi_datatype_primitive.hpp
@@ -50,7 +50,7 @@ public:
: is_committed(false),
origin()
{
-#if defined(MPI_VERSION) && MPI_VERSION >= 2
+#if BOOST_MPI_VERSION >= 2
BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast<void*>(orig), &origin));
#else
BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(orig), &origin));
@@ -77,7 +77,7 @@ public:
{
if (!is_committed)
{
-#if defined(MPI_VERSION) && MPI_VERSION >= 2
+#if BOOST_MPI_VERSION >= 2
BOOST_MPI_CHECK_RESULT(MPI_Type_create_struct,
(
addresses.size(),
@@ -120,7 +120,7 @@ private:
// store address, type and length
MPI_Aint a;
-#if defined(MPI_VERSION) && MPI_VERSION >= 2
+#if BOOST_MPI_VERSION >= 2
BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast<void*>(p), &a));
#else
BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(p), &a));
diff --git a/boost/mpi/detail/offsets.hpp b/boost/mpi/detail/offsets.hpp
index 7e5ab7dff6..0cfc9c9331 100644
--- a/boost/mpi/detail/offsets.hpp
+++ b/boost/mpi/detail/offsets.hpp
@@ -9,6 +9,7 @@
#define BOOST_MPI_OFFSETS_HPP
#include <vector>
+#include <boost/mpi/config.hpp>
#include <boost/mpi/communicator.hpp>
namespace boost { namespace mpi {
@@ -16,10 +17,10 @@ namespace detail {
// Convert a sequence of sizes [S0..Sn] to a sequence displacement
// [O0..On] where O[0] = 0 and O[k+1] = O[k]+S[k].
-void sizes2offsets(int const* sizes, int* offsets, int n);
+void BOOST_MPI_DECL sizes2offsets(int const* sizes, int* offsets, int n);
// Same as size2offset(sizes.data(), offsets.data(), sizes.size())
-void sizes2offsets(std::vector<int> const& sizes, std::vector<int>& offsets);
+void BOOST_MPI_DECL sizes2offsets(std::vector<int> const& sizes, std::vector<int>& offsets);
// Given a sequence of sizes (typically the number of records dispatched
// to each process in a scater) and a sequence of displacements (typically the
diff --git a/boost/mpi/detail/point_to_point.hpp b/boost/mpi/detail/point_to_point.hpp
index 06db34ce94..74116cf8e5 100644
--- a/boost/mpi/detail/point_to_point.hpp
+++ b/boost/mpi/detail/point_to_point.hpp
@@ -13,11 +13,16 @@
#include <boost/mpi/packed_oarchive.hpp>
#include <boost/mpi/packed_iarchive.hpp>
-namespace boost { namespace mpi { namespace detail {
+namespace boost { namespace mpi {
+
+class request;
+class communicator;
+
+namespace detail {
/** Sends a packed archive using MPI_Send. */
BOOST_MPI_DECL void
-packed_archive_send(MPI_Comm comm, int dest, int tag,
+packed_archive_send(communicator const& comm, int dest, int tag,
const packed_oarchive& ar);
/** Sends a packed archive using MPI_Isend.
@@ -26,25 +31,21 @@ packed_archive_send(MPI_Comm comm, int dest, int tag,
* for each packet will be placed into the out_requests array, up to
* num_out_requests packets. The number of packets sent will be
* returned from the function.
- *
- * @pre num_out_requests >= 2
*/
-BOOST_MPI_DECL int
-packed_archive_isend(MPI_Comm comm, int dest, int tag,
- const packed_oarchive& ar,
- MPI_Request* out_requests, int num_out_requests);
+BOOST_MPI_DECL request
+packed_archive_isend(communicator const& comm, int dest, int tag,
+ const packed_oarchive& ar);
/**
* \overload
*/
-BOOST_MPI_DECL int
-packed_archive_isend(MPI_Comm comm, int dest, int tag,
- const packed_iarchive& ar,
- MPI_Request* out_requests, int num_out_requests);
+BOOST_MPI_DECL request
+packed_archive_isend(communicator const& comm, int dest, int tag,
+ const packed_iarchive& ar);
/** Receives a packed archive using MPI_Recv. */
BOOST_MPI_DECL void
-packed_archive_recv(MPI_Comm comm, int source, int tag, packed_iarchive& ar,
+packed_archive_recv(communicator const& comm, int source, int tag, packed_iarchive& ar,
MPI_Status& status);
} } } // end namespace boost::mpi::detail
diff --git a/boost/mpi/detail/request_handlers.hpp b/boost/mpi/detail/request_handlers.hpp
new file mode 100644
index 0000000000..2ad627639d
--- /dev/null
+++ b/boost/mpi/detail/request_handlers.hpp
@@ -0,0 +1,631 @@
+// Copyright (C) 2018 Alain Miniussi <alain.miniussi@oca.eu>.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Request implementation dtails
+
+// This header should be included only after the communicator and request
+// classes has been defined.
+#ifndef BOOST_MPI_REQUEST_HANDLERS_HPP
+#define BOOST_MPI_REQUEST_HANDLERS_HPP
+
+#include <boost/mpi/skeleton_and_content_types.hpp>
+
+namespace boost { namespace mpi {
+
+namespace detail {
+/**
+ * Internal data structure that stores everything required to manage
+ * the receipt of serialized data via a request object.
+ */
+template<typename T>
+struct serialized_irecv_data {
+ serialized_irecv_data(const communicator& comm, T& value)
+ : m_ia(comm), m_value(value) {}
+
+ void deserialize(status& stat)
+ {
+ m_ia >> m_value;
+ stat.m_count = 1;
+ }
+
+ std::size_t m_count;
+ packed_iarchive m_ia;
+ T& m_value;
+};
+
+template<>
+struct serialized_irecv_data<packed_iarchive>
+{
+ serialized_irecv_data(communicator const&, packed_iarchive& ia) : m_ia(ia) { }
+
+ void deserialize(status&) { /* Do nothing. */ }
+
+ std::size_t m_count;
+ packed_iarchive& m_ia;
+};
+
+/**
+ * Internal data structure that stores everything required to manage
+ * the receipt of an array of serialized data via a request object.
+ */
+template<typename T>
+struct serialized_array_irecv_data
+{
+ serialized_array_irecv_data(const communicator& comm, T* values, int n)
+ : m_count(0), m_ia(comm), m_values(values), m_nb(n) {}
+
+ void deserialize(status& stat);
+
+ std::size_t m_count;
+ packed_iarchive m_ia;
+ T* m_values;
+ int m_nb;
+};
+
+template<typename T>
+void serialized_array_irecv_data<T>::deserialize(status& stat)
+{
+ T* v = m_values;
+ T* end = m_values+m_nb;
+ while (v < end) {
+ m_ia >> *v++;
+ }
+ stat.m_count = m_nb;
+}
+
+/**
+ * Internal data structure that stores everything required to manage
+ * the receipt of an array of primitive data but unknown size.
+ * Such an array can have been send with blocking operation and so must
+ * be compatible with the (size_t,raw_data[]) format.
+ */
+template<typename T, class A>
+struct dynamic_array_irecv_data
+{
+ BOOST_STATIC_ASSERT_MSG(is_mpi_datatype<T>::value, "Can only be specialized for MPI datatypes.");
+
+ dynamic_array_irecv_data(std::vector<T,A>& values)
+ : m_count(-1), m_values(values) {}
+
+ std::size_t m_count;
+ std::vector<T,A>& m_values;
+};
+
+template<typename T>
+struct serialized_irecv_data<const skeleton_proxy<T> >
+{
+ serialized_irecv_data(const communicator& comm, skeleton_proxy<T> proxy)
+ : m_isa(comm), m_ia(m_isa.get_skeleton()), m_proxy(proxy) { }
+
+ void deserialize(status& stat)
+ {
+ m_isa >> m_proxy.object;
+ stat.m_count = 1;
+ }
+
+ std::size_t m_count;
+ packed_skeleton_iarchive m_isa;
+ packed_iarchive& m_ia;
+ skeleton_proxy<T> m_proxy;
+};
+
+template<typename T>
+struct serialized_irecv_data<skeleton_proxy<T> >
+ : public serialized_irecv_data<const skeleton_proxy<T> >
+{
+ typedef serialized_irecv_data<const skeleton_proxy<T> > inherited;
+
+ serialized_irecv_data(const communicator& comm, const skeleton_proxy<T>& proxy)
+ : inherited(comm, proxy) { }
+};
+}
+
+#if BOOST_MPI_VERSION >= 3
+template<class Data>
+class request::probe_handler
+ : public request::handler,
+ protected Data {
+
+protected:
+ template<typename I1>
+ probe_handler(communicator const& comm, int source, int tag, I1& i1)
+ : Data(comm, i1),
+ m_comm(comm),
+ m_source(source),
+ m_tag(tag) {}
+ // no variadic template for now
+ template<typename I1, typename I2>
+ probe_handler(communicator const& comm, int source, int tag, I1& i1, I2& i2)
+ : Data(comm, i1, i2),
+ m_comm(comm),
+ m_source(source),
+ m_tag(tag) {}
+
+public:
+ bool active() const { return m_source != MPI_PROC_NULL; }
+ optional<MPI_Request&> trivial() { return boost::none; }
+ void cancel() { m_source = MPI_PROC_NULL; }
+
+ status wait() {
+ MPI_Message msg;
+ status stat;
+ BOOST_MPI_CHECK_RESULT(MPI_Mprobe, (m_source,m_tag,m_comm,&msg,&stat.m_status));
+ return unpack(msg, stat);
+ }
+
+ optional<status> test() {
+ status stat;
+ int flag = 0;
+ MPI_Message msg;
+ BOOST_MPI_CHECK_RESULT(MPI_Improbe, (m_source,m_tag,m_comm,&flag,&msg,&stat.m_status));
+ if (flag) {
+ return unpack(msg, stat);
+ } else {
+ return optional<status>();
+ }
+ }
+
+protected:
+ friend class request;
+
+ status unpack(MPI_Message& msg, status& stat) {
+ int count;
+ MPI_Datatype datatype = this->Data::datatype();
+ BOOST_MPI_CHECK_RESULT(MPI_Get_count, (&stat.m_status, datatype, &count));
+ this->Data::resize(count);
+ BOOST_MPI_CHECK_RESULT(MPI_Mrecv, (this->Data::buffer(), count, datatype, &msg, &stat.m_status));
+ this->Data::deserialize();
+ m_source = MPI_PROC_NULL;
+ stat.m_count = 1;
+ return stat;
+ }
+
+ communicator const& m_comm;
+ int m_source;
+ int m_tag;
+};
+#endif // BOOST_MPI_VERSION >= 3
+
+namespace detail {
+template<class A>
+struct dynamic_primitive_array_data {
+ dynamic_primitive_array_data(communicator const&, A& arr) : m_buffer(arr) {}
+
+ void* buffer() { return m_buffer.data(); }
+ void resize(std::size_t sz) { m_buffer.resize(sz); }
+ void deserialize() {}
+ MPI_Datatype datatype() { return get_mpi_datatype<typename A::value_type>(); }
+
+ A& m_buffer;
+};
+
+template<typename T>
+struct serialized_data {
+ serialized_data(communicator const& comm, T& value) : m_archive(comm), m_value(value) {}
+
+ void* buffer() { return m_archive.address(); }
+ void resize(std::size_t sz) { m_archive.resize(sz); }
+ void deserialize() { m_archive >> m_value; }
+ MPI_Datatype datatype() { return MPI_PACKED; }
+
+ packed_iarchive m_archive;
+ T& m_value;
+};
+
+template<>
+struct serialized_data<packed_iarchive> {
+ serialized_data(communicator const& comm, packed_iarchive& ar) : m_archive(ar) {}
+
+ void* buffer() { return m_archive.address(); }
+ void resize(std::size_t sz) { m_archive.resize(sz); }
+ void deserialize() {}
+ MPI_Datatype datatype() { return MPI_PACKED; }
+
+ packed_iarchive& m_archive;
+};
+
+template<typename T>
+struct serialized_data<const skeleton_proxy<T> > {
+ serialized_data(communicator const& comm, skeleton_proxy<T> skel)
+ : m_proxy(skel),
+ m_archive(comm) {}
+
+ void* buffer() { return m_archive.get_skeleton().address(); }
+ void resize(std::size_t sz) { m_archive.get_skeleton().resize(sz); }
+ void deserialize() { m_archive >> m_proxy.object; }
+ MPI_Datatype datatype() { return MPI_PACKED; }
+
+ skeleton_proxy<T> m_proxy;
+ packed_skeleton_iarchive m_archive;
+};
+
+template<typename T>
+struct serialized_data<skeleton_proxy<T> >
+ : public serialized_data<const skeleton_proxy<T> > {
+ typedef serialized_data<const skeleton_proxy<T> > super;
+ serialized_data(communicator const& comm, skeleton_proxy<T> skel)
+ : super(comm, skel) {}
+};
+
+template<typename T>
+struct serialized_array_data {
+ serialized_array_data(communicator const& comm, T* values, int nb)
+ : m_archive(comm), m_values(values), m_nb(nb) {}
+
+ void* buffer() { return m_archive.address(); }
+ void resize(std::size_t sz) { m_archive.resize(sz); }
+ void deserialize() {
+ T* end = m_values + m_nb;
+ T* v = m_values;
+ while (v != end) {
+ m_archive >> *v++;
+ }
+ }
+ MPI_Datatype datatype() { return MPI_PACKED; }
+
+ packed_iarchive m_archive;
+ T* m_values;
+ int m_nb;
+};
+
+}
+
+class request::legacy_handler : public request::handler {
+public:
+ legacy_handler(communicator const& comm, int source, int tag);
+
+ void cancel() {
+ for (int i = 0; i < 2; ++i) {
+ if (m_requests[i] != MPI_REQUEST_NULL) {
+ BOOST_MPI_CHECK_RESULT(MPI_Cancel, (m_requests+i));
+ }
+ }
+ }
+
+ bool active() const;
+ optional<MPI_Request&> trivial();
+
+ MPI_Request m_requests[2];
+ communicator m_comm;
+ int m_source;
+ int m_tag;
+};
+
+template<typename T>
+class request::legacy_serialized_handler
+ : public request::legacy_handler,
+ protected detail::serialized_irecv_data<T> {
+public:
+ typedef detail::serialized_irecv_data<T> extra;
+ legacy_serialized_handler(communicator const& comm, int source, int tag, T& value)
+ : legacy_handler(comm, source, tag),
+ extra(comm, value) {
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (&this->extra::m_count, 1,
+ get_mpi_datatype(this->extra::m_count),
+ source, tag, comm, m_requests+0));
+
+ }
+
+ status wait() {
+ status stat;
+ if (m_requests[1] == MPI_REQUEST_NULL) {
+ // Wait for the count message to complete
+ BOOST_MPI_CHECK_RESULT(MPI_Wait,
+ (m_requests, &stat.m_status));
+ // Resize our buffer and get ready to receive its data
+ this->extra::m_ia.resize(this->extra::m_count);
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (this->extra::m_ia.address(), this->extra::m_ia.size(), MPI_PACKED,
+ stat.source(), stat.tag(),
+ MPI_Comm(m_comm), m_requests + 1));
+ }
+
+ // Wait until we have received the entire message
+ BOOST_MPI_CHECK_RESULT(MPI_Wait,
+ (m_requests + 1, &stat.m_status));
+
+ this->deserialize(stat);
+ return stat;
+ }
+
+ optional<status> test() {
+ status stat;
+ int flag = 0;
+
+ if (m_requests[1] == MPI_REQUEST_NULL) {
+ // Check if the count message has completed
+ BOOST_MPI_CHECK_RESULT(MPI_Test,
+ (m_requests, &flag, &stat.m_status));
+ if (flag) {
+ // Resize our buffer and get ready to receive its data
+ this->extra::m_ia.resize(this->extra::m_count);
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (this->extra::m_ia.address(), this->extra::m_ia.size(),MPI_PACKED,
+ stat.source(), stat.tag(),
+ MPI_Comm(m_comm), m_requests + 1));
+ } else
+ return optional<status>(); // We have not finished yet
+ }
+
+ // Check if we have received the message data
+ BOOST_MPI_CHECK_RESULT(MPI_Test,
+ (m_requests + 1, &flag, &stat.m_status));
+ if (flag) {
+ this->deserialize(stat);
+ return stat;
+ } else
+ return optional<status>();
+ }
+};
+
+template<typename T>
+class request::legacy_serialized_array_handler
+ : public request::legacy_handler,
+ protected detail::serialized_array_irecv_data<T> {
+ typedef detail::serialized_array_irecv_data<T> extra;
+
+public:
+ legacy_serialized_array_handler(communicator const& comm, int source, int tag, T* values, int n)
+ : legacy_handler(comm, source, tag),
+ extra(comm, values, n) {
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (&this->extra::m_count, 1,
+ get_mpi_datatype(this->extra::m_count),
+ source, tag, comm, m_requests+0));
+ }
+
+ status wait() {
+ status stat;
+ if (m_requests[1] == MPI_REQUEST_NULL) {
+ // Wait for the count message to complete
+ BOOST_MPI_CHECK_RESULT(MPI_Wait,
+ (m_requests, &stat.m_status));
+ // Resize our buffer and get ready to receive its data
+ this->extra::m_ia.resize(this->extra::m_count);
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (this->extra::m_ia.address(), this->extra::m_ia.size(), MPI_PACKED,
+ stat.source(), stat.tag(),
+ MPI_Comm(m_comm), m_requests + 1));
+ }
+
+ // Wait until we have received the entire message
+ BOOST_MPI_CHECK_RESULT(MPI_Wait,
+ (m_requests + 1, &stat.m_status));
+
+ this->deserialize(stat);
+ return stat;
+ }
+
+ optional<status> test() {
+ status stat;
+ int flag = 0;
+
+ if (m_requests[1] == MPI_REQUEST_NULL) {
+ // Check if the count message has completed
+ BOOST_MPI_CHECK_RESULT(MPI_Test,
+ (m_requests, &flag, &stat.m_status));
+ if (flag) {
+ // Resize our buffer and get ready to receive its data
+ this->extra::m_ia.resize(this->extra::m_count);
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (this->extra::m_ia.address(), this->extra::m_ia.size(),MPI_PACKED,
+ stat.source(), stat.tag(),
+ MPI_Comm(m_comm), m_requests + 1));
+ } else
+ return optional<status>(); // We have not finished yet
+ }
+
+ // Check if we have received the message data
+ BOOST_MPI_CHECK_RESULT(MPI_Test,
+ (m_requests + 1, &flag, &stat.m_status));
+ if (flag) {
+ this->deserialize(stat);
+ return stat;
+ } else
+ return optional<status>();
+ }
+};
+
+template<typename T, class A>
+class request::legacy_dynamic_primitive_array_handler
+ : public request::legacy_handler,
+ protected detail::dynamic_array_irecv_data<T,A>
+{
+ typedef detail::dynamic_array_irecv_data<T,A> extra;
+
+public:
+ legacy_dynamic_primitive_array_handler(communicator const& comm, int source, int tag, std::vector<T,A>& values)
+ : legacy_handler(comm, source, tag),
+ extra(values) {
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (&this->extra::m_count, 1,
+ get_mpi_datatype(this->extra::m_count),
+ source, tag, comm, m_requests+0));
+ }
+
+ status wait() {
+ status stat;
+ if (m_requests[1] == MPI_REQUEST_NULL) {
+ // Wait for the count message to complete
+ BOOST_MPI_CHECK_RESULT(MPI_Wait,
+ (m_requests, &stat.m_status));
+ // Resize our buffer and get ready to receive its data
+ this->extra::m_values.resize(this->extra::m_count);
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (&(this->extra::m_values[0]), this->extra::m_values.size(), get_mpi_datatype<T>(),
+ stat.source(), stat.tag(),
+ MPI_Comm(m_comm), m_requests + 1));
+ }
+ // Wait until we have received the entire message
+ BOOST_MPI_CHECK_RESULT(MPI_Wait,
+ (m_requests + 1, &stat.m_status));
+ return stat;
+ }
+
+ optional<status> test() {
+ status stat;
+ int flag = 0;
+
+ if (m_requests[1] == MPI_REQUEST_NULL) {
+ // Check if the count message has completed
+ BOOST_MPI_CHECK_RESULT(MPI_Test,
+ (m_requests, &flag, &stat.m_status));
+ if (flag) {
+ // Resize our buffer and get ready to receive its data
+ this->extra::m_values.resize(this->extra::m_count);
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (&(this->extra::m_values[0]), this->extra::m_values.size(),MPI_PACKED,
+ stat.source(), stat.tag(),
+ MPI_Comm(m_comm), m_requests + 1));
+ } else
+ return optional<status>(); // We have not finished yet
+ }
+
+ // Check if we have received the message data
+ BOOST_MPI_CHECK_RESULT(MPI_Test,
+ (m_requests + 1, &flag, &stat.m_status));
+ if (flag) {
+ return stat;
+ } else
+ return optional<status>();
+ }
+};
+
+class request::trivial_handler : public request::handler {
+
+public:
+ trivial_handler();
+
+ status wait();
+ optional<status> test();
+ void cancel();
+
+ bool active() const;
+ optional<MPI_Request&> trivial();
+
+private:
+ friend class request;
+ MPI_Request m_request;
+};
+
+class request::dynamic_handler : public request::handler {
+ dynamic_handler();
+
+ status wait();
+ optional<status> test();
+ void cancel();
+
+ bool active() const;
+ optional<MPI_Request&> trivial();
+
+private:
+ friend class request;
+ MPI_Request m_requests[2];
+};
+
+template<typename T>
+request request::make_serialized(communicator const& comm, int source, int tag, T& value) {
+#if defined(BOOST_MPI_USE_IMPROBE)
+ return request(new probe_handler<detail::serialized_data<T> >(comm, source, tag, value));
+#else
+ return request(new legacy_serialized_handler<T>(comm, source, tag, value));
+#endif
+}
+
+template<typename T>
+request request::make_serialized_array(communicator const& comm, int source, int tag, T* values, int n) {
+#if defined(BOOST_MPI_USE_IMPROBE)
+ return request(new probe_handler<detail::serialized_array_data<T> >(comm, source, tag, values, n));
+#else
+ return request(new legacy_serialized_array_handler<T>(comm, source, tag, values, n));
+#endif
+}
+
+template<typename T, class A>
+request request::make_dynamic_primitive_array_recv(communicator const& comm, int source, int tag,
+ std::vector<T,A>& values) {
+#if defined(BOOST_MPI_USE_IMPROBE)
+ return request(new probe_handler<detail::dynamic_primitive_array_data<std::vector<T,A> > >(comm,source,tag,values));
+#else
+ return request(new legacy_dynamic_primitive_array_handler<T,A>(comm, source, tag, values));
+#endif
+}
+
+template<typename T>
+request
+request::make_trivial_send(communicator const& comm, int dest, int tag, T const* values, int n) {
+ trivial_handler* handler = new trivial_handler;
+ BOOST_MPI_CHECK_RESULT(MPI_Isend,
+ (const_cast<T*>(values), n,
+ get_mpi_datatype<T>(),
+ dest, tag, comm, &handler->m_request));
+ return request(handler);
+}
+
+template<typename T>
+request
+request::make_trivial_send(communicator const& comm, int dest, int tag, T const& value) {
+ return make_trivial_send(comm, dest, tag, &value, 1);
+}
+
+template<typename T>
+request
+request::make_trivial_recv(communicator const& comm, int dest, int tag, T* values, int n) {
+ trivial_handler* handler = new trivial_handler;
+ BOOST_MPI_CHECK_RESULT(MPI_Irecv,
+ (values, n,
+ get_mpi_datatype<T>(),
+ dest, tag, comm, &handler->m_request));
+ return request(handler);
+}
+
+template<typename T>
+request
+request::make_trivial_recv(communicator const& comm, int dest, int tag, T& value) {
+ return make_trivial_recv(comm, dest, tag, &value, 1);
+}
+
+template<typename T, class A>
+request request::make_dynamic_primitive_array_send(communicator const& comm, int dest, int tag,
+ std::vector<T,A> const& values) {
+#if defined(BOOST_MPI_USE_IMPROBE)
+ return make_trivial_send(comm, dest, tag, values.data(), values.size());
+#else
+ {
+ // non blocking recv by legacy_dynamic_primitive_array_handler
+ // blocking recv by status recv_vector(source,tag,value,primitive)
+ boost::shared_ptr<std::size_t> size(new std::size_t(values.size()));
+ dynamic_handler* handler = new dynamic_handler;
+ request req(handler);
+ req.preserve(size);
+
+ BOOST_MPI_CHECK_RESULT(MPI_Isend,
+ (size.get(), 1,
+ get_mpi_datatype(*size),
+ dest, tag, comm, handler->m_requests+0));
+ BOOST_MPI_CHECK_RESULT(MPI_Isend,
+ (const_cast<T*>(values.data()), *size,
+ get_mpi_datatype<T>(),
+ dest, tag, comm, handler->m_requests+1));
+ return req;
+ }
+#endif
+}
+
+inline
+request::legacy_handler::legacy_handler(communicator const& comm, int source, int tag)
+ : m_comm(comm),
+ m_source(source),
+ m_tag(tag)
+{
+ m_requests[0] = MPI_REQUEST_NULL;
+ m_requests[1] = MPI_REQUEST_NULL;
+}
+
+}}
+
+#endif // BOOST_MPI_REQUEST_HANDLERS_HPP
diff --git a/boost/mpi/nonblocking.hpp b/boost/mpi/nonblocking.hpp
index cf762d9cfb..fe944be8ee 100644
--- a/boost/mpi/nonblocking.hpp
+++ b/boost/mpi/nonblocking.hpp
@@ -59,10 +59,7 @@ wait_any(ForwardIterator first, ForwardIterator last)
ForwardIterator current = first;
while (true) {
// Check if we have found a completed request. If so, return it.
- bool current_is_active =
- ( current->m_requests[0] != MPI_REQUEST_NULL ||
- current->m_requests[1] != MPI_REQUEST_NULL) ;
- if (current_is_active) {
+ if (current->active()) {
optional<status> result = current->test();
if (bool(result)) {
return std::make_pair(*result, current);
@@ -75,10 +72,7 @@ wait_any(ForwardIterator first, ForwardIterator last)
// We could probably ignore non trivial request that are inactive,
// but we can assume that a mix of trivial and non trivial requests
// is unlikely enough not to care.
- bool current_trivial_request =
- ( !bool(current->m_handler) &&
- current->m_requests[1] == MPI_REQUEST_NULL);
- all_trivial_requests = all_trivial_requests && current_trivial_request;
+ all_trivial_requests = all_trivial_requests && current->trivial();
// Move to the next request.
++n;
@@ -89,8 +83,9 @@ wait_any(ForwardIterator first, ForwardIterator last)
if (all_trivial_requests) {
std::vector<MPI_Request> requests;
requests.reserve(n);
- for (current = first; current != last; ++current)
- requests.push_back(current->m_requests[0]);
+ for (current = first; current != last; ++current) {
+ requests.push_back(*current->trivial());
+ }
// Let MPI wait until one of these operations completes.
int index;
@@ -106,7 +101,7 @@ wait_any(ForwardIterator first, ForwardIterator last)
// Find the iterator corresponding to the completed request.
current = first;
advance(current, index);
- current->m_requests[0] = requests[index];
+ *current->trivial() = requests[index];
return std::make_pair(stat, current);
}
@@ -209,10 +204,7 @@ wait_all(ForwardIterator first, ForwardIterator last, OutputIterator out)
// Check if this request (and all others before it) are "trivial"
// requests, e.g., they can be represented with a single
// MPI_Request.
- all_trivial_requests =
- all_trivial_requests
- && !current->m_handler
- && current->m_requests[1] == MPI_REQUEST_NULL;
+ all_trivial_requests = all_trivial_requests && current->trivial();
}
}
}
@@ -225,7 +217,7 @@ wait_all(ForwardIterator first, ForwardIterator last, OutputIterator out)
std::vector<MPI_Request> requests;
requests.reserve(num_outstanding_requests);
for (ForwardIterator current = first; current != last; ++current)
- requests.push_back(current->m_requests[0]);
+ requests.push_back(*current->trivial());
// Let MPI wait until all of these operations completes.
std::vector<MPI_Status> stats(num_outstanding_requests);
@@ -263,7 +255,7 @@ wait_all(ForwardIterator first, ForwardIterator last)
difference_type num_outstanding_requests = distance(first, last);
- std::vector<bool> completed(num_outstanding_requests);
+ std::vector<bool> completed(num_outstanding_requests, false);
while (num_outstanding_requests > 0) {
bool all_trivial_requests = true;
@@ -280,10 +272,7 @@ wait_all(ForwardIterator first, ForwardIterator last)
// Check if this request (and all others before it) are "trivial"
// requests, e.g., they can be represented with a single
// MPI_Request.
- all_trivial_requests =
- all_trivial_requests
- && !current->m_handler
- && current->m_requests[1] == MPI_REQUEST_NULL;
+ all_trivial_requests = all_trivial_requests && current->trivial();
}
}
}
@@ -296,7 +285,7 @@ wait_all(ForwardIterator first, ForwardIterator last)
std::vector<MPI_Request> requests;
requests.reserve(num_outstanding_requests);
for (ForwardIterator current = first; current != last; ++current)
- requests.push_back(current->m_requests[0]);
+ requests.push_back(*current->trivial());
// Let MPI wait until all of these operations completes.
BOOST_MPI_CHECK_RESULT(MPI_Waitall,
@@ -348,10 +337,10 @@ test_all(ForwardIterator first, ForwardIterator last, OutputIterator out)
for (; first != last; ++first) {
// If we have a non-trivial request, then no requests can be
// completed.
- if (first->m_handler || first->m_requests[1] != MPI_REQUEST_NULL)
+ if (!first->trivial()) {
return optional<OutputIterator>();
-
- requests.push_back(first->m_requests[0]);
+ }
+ requests.push_back(*first->trivial());
}
int flag = 0;
@@ -381,10 +370,10 @@ test_all(ForwardIterator first, ForwardIterator last)
for (; first != last; ++first) {
// If we have a non-trivial request, then no requests can be
// completed.
- if (first->m_handler || first->m_requests[1] != MPI_REQUEST_NULL)
+ if (!first->trivial()) {
return false;
-
- requests.push_back(first->m_requests[0]);
+ }
+ requests.push_back(*first->trivial());
}
int flag = 0;
@@ -467,10 +456,7 @@ wait_some(BidirectionalIterator first, BidirectionalIterator last,
// Check if this request (and all others before it) are "trivial"
// requests, e.g., they can be represented with a single
// MPI_Request.
- all_trivial_requests =
- all_trivial_requests
- && !current->m_handler
- && current->m_requests[1] == MPI_REQUEST_NULL;
+ all_trivial_requests = all_trivial_requests && current->trivial();
// Move to the next request.
++n;
@@ -492,7 +478,7 @@ wait_some(BidirectionalIterator first, BidirectionalIterator last,
std::vector<MPI_Status> stats(n);
requests.reserve(n);
for (current = first; current != last; ++current)
- requests.push_back(current->m_requests[0]);
+ requests.push_back(*current->trivial());
// Let MPI wait until some of these operations complete.
int num_completed;
@@ -518,7 +504,7 @@ wait_some(BidirectionalIterator first, BidirectionalIterator last,
// Finish up the request and swap it into the "completed
// requests" partition.
- current->m_requests[0] = requests[indices[index]];
+ *current->trivial() = requests[indices[index]];
--start_of_completed;
iter_swap(current, start_of_completed);
}
@@ -583,10 +569,7 @@ wait_some(BidirectionalIterator first, BidirectionalIterator last)
// Check if this request (and all others before it) are "trivial"
// requests, e.g., they can be represented with a single
// MPI_Request.
- all_trivial_requests =
- all_trivial_requests
- && !current->m_handler
- && current->m_requests[1] == MPI_REQUEST_NULL;
+ all_trivial_requests = all_trivial_requests && current->trivial();
// Move to the next request.
++n;
@@ -603,7 +586,7 @@ wait_some(BidirectionalIterator first, BidirectionalIterator last)
std::vector<int> indices(n);
requests.reserve(n);
for (current = first; current != last; ++current)
- requests.push_back(current->m_requests[0]);
+ requests.push_back(*current->trivial());
// Let MPI wait until some of these operations complete.
int num_completed;
@@ -624,7 +607,7 @@ wait_some(BidirectionalIterator first, BidirectionalIterator last)
// Finish up the request and swap it into the "completed
// requests" partition.
- current->m_requests[0] = requests[indices[index]];
+ *current->trivial() = requests[indices[index]];
--start_of_completed;
iter_swap(current, start_of_completed);
}
diff --git a/boost/mpi/operations.hpp b/boost/mpi/operations.hpp
index 5af8c8fafa..8988491c99 100644
--- a/boost/mpi/operations.hpp
+++ b/boost/mpi/operations.hpp
@@ -23,7 +23,8 @@
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpi/datatype.hpp>
-#include <boost/utility/enable_if.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/core/uncaught_exceptions.hpp>
#include <functional>
namespace boost { namespace mpi {
@@ -302,7 +303,7 @@ namespace detail {
~user_op()
{
- if (std::uncaught_exception()) {
+ if (boost::core::uncaught_exceptions() > 0) {
// Ignore failure cases: there are obviously other problems
// already, and we don't want to cause program termination if
// MPI_Op_free fails.
diff --git a/boost/mpi/request.hpp b/boost/mpi/request.hpp
index 16a2fb18f9..8732cd2b56 100644
--- a/boost/mpi/request.hpp
+++ b/boost/mpi/request.hpp
@@ -13,6 +13,7 @@
#define BOOST_MPI_REQUEST_HPP
#include <boost/mpi/config.hpp>
+#include <boost/mpi/status.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/mpi/packed_iarchive.hpp>
@@ -38,11 +39,60 @@ class BOOST_MPI_DECL request
request();
/**
+ * Send a known number of primitive objects in one MPI request.
+ */
+ template<typename T>
+ static request make_trivial_send(communicator const& comm, int dest, int tag, T const& value);
+ template<typename T>
+ static request make_trivial_send(communicator const& comm, int dest, int tag, T const* values, int n);
+ static request make_packed_send(communicator const& comm, int dest, int tag, void const* values, std::size_t n);
+
+ static request make_bottom_send(communicator const& comm, int dest, int tag, MPI_Datatype tp);
+ static request make_empty_send(communicator const& comm, int dest, int tag);
+ /**
+ * Receive a known number of primitive objects in one MPI request.
+ */
+ template<typename T>
+ static request make_trivial_recv(communicator const& comm, int dest, int tag, T& value);
+ template<typename T>
+ static request make_trivial_recv(communicator const& comm, int dest, int tag, T* values, int n);
+
+ static request make_bottom_recv(communicator const& comm, int dest, int tag, MPI_Datatype tp);
+ static request make_empty_recv(communicator const& comm, int dest, int tag);
+ /**
+ * Construct request for simple data of unknown size.
+ */
+ static request make_dynamic();
+ /**
+ * Constructs request for serialized data.
+ */
+ template<typename T>
+ static request make_serialized(communicator const& comm, int source, int tag, T& value);
+ /**
+ * Constructs request for array of complex data.
+ */
+ template<typename T>
+ static request make_serialized_array(communicator const& comm, int source, int tag, T* values, int n);
+ /**
+ * Request to recv array of primitive data.
+ */
+ template<typename T, class A>
+ static request
+ make_dynamic_primitive_array_recv(communicator const& comm, int source, int tag,
+ std::vector<T,A>& values);
+ /**
+ * Request to send array of primitive data.
+ */
+ template<typename T, class A>
+ static request
+ make_dynamic_primitive_array_send(communicator const& comm, int source, int tag,
+ std::vector<T,A> const& values);
+ /**
* Wait until the communication associated with this request has
* completed, then return a @c status object describing the
* communication.
*/
- status wait();
+ status wait() { return m_handler ? m_handler->wait() : status(); }
/**
* Determine whether the communication associated with this request
@@ -52,58 +102,58 @@ class BOOST_MPI_DECL request
* yet. Note that once @c test() returns a @c status object, the
* request has completed and @c wait() should not be called.
*/
- optional<status> test();
+ optional<status> test() { return active() ? m_handler->test() : optional<status>(); }
/**
* Cancel a pending communication, assuming it has not already been
* completed.
*/
- void cancel();
-
- private:
- enum request_action { ra_wait, ra_test, ra_cancel };
- typedef optional<status> (*handler_type)(request* self,
- request_action action);
-
+ void cancel() { if (m_handler) { m_handler->cancel(); } m_preserved.reset(); }
+
/**
- * INTERNAL ONLY
- *
- * Handles the non-blocking receive of a serialized value.
+ * The trivial MPI requet implenting this request, provided it's trivial.
+ * Probably irrelevant to most users.
*/
- template<typename T>
- static optional<status>
- handle_serialized_irecv(request* self, request_action action);
+ optional<MPI_Request&> trivial() { return (m_handler
+ ? m_handler->trivial()
+ : optional<MPI_Request&>()); }
/**
- * INTERNAL ONLY
- *
- * Handles the non-blocking receive of an array of serialized values.
+ * Is this request potentialy pending ?
*/
- template<typename T>
- static optional<status>
- handle_serialized_array_irecv(request* self, request_action action);
-
- /**
- * INTERNAL ONLY
- *
- * Handles the non-blocking receive of a dynamic array of primitive values.
- */
- template<typename T, class A>
- static optional<status>
- handle_dynamic_primitive_array_irecv(request* self, request_action action);
-
- public: // template friends are not portable
-
- /// INTERNAL ONLY
- MPI_Request m_requests[2];
-
- /// INTERNAL ONLY
- handler_type m_handler;
-
- /// INTERNAL ONLY
- shared_ptr<void> m_data;
-
- friend class communicator;
+ bool active() const { return bool(m_handler) && m_handler->active(); }
+
+ // Some data might need protection while the reqest is processed.
+ void preserve(boost::shared_ptr<void> d);
+
+ class handler {
+ public:
+ virtual ~handler() = 0;
+ virtual status wait() = 0;
+ virtual optional<status> test() = 0;
+ virtual void cancel() = 0;
+
+ virtual bool active() const = 0;
+ virtual optional<MPI_Request&> trivial() = 0;
+ };
+
+ private:
+
+ request(handler *h) : m_handler(h) {};
+
+ // specific implementations
+ class legacy_handler;
+ class trivial_handler;
+ class dynamic_handler;
+ template<typename T> class legacy_serialized_handler;
+ template<typename T> class legacy_serialized_array_handler;
+ template<typename T, class A> class legacy_dynamic_primitive_array_handler;
+#if BOOST_MPI_VERSION >= 3
+ template<class Data> class probe_handler;
+#endif
+ private:
+ shared_ptr<handler> m_handler;
+ shared_ptr<void> m_preserved;
};
} } // end namespace boost::mpi
diff --git a/boost/mpi/skeleton_and_content.hpp b/boost/mpi/skeleton_and_content.hpp
index dcd13bfe57..20fc135e23 100644
--- a/boost/mpi/skeleton_and_content.hpp
+++ b/boost/mpi/skeleton_and_content.hpp
@@ -25,338 +25,10 @@
#include <boost/mpi/config.hpp>
#include <boost/archive/detail/auto_link_archive.hpp>
-#include <boost/mpi/packed_iarchive.hpp>
-#include <boost/mpi/packed_oarchive.hpp>
-#include <boost/mpi/detail/forward_skeleton_iarchive.hpp>
-#include <boost/mpi/detail/forward_skeleton_oarchive.hpp>
-#include <boost/mpi/detail/ignore_iprimitive.hpp>
-#include <boost/mpi/detail/ignore_oprimitive.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/archive/detail/register_archive.hpp>
+#include <boost/mpi/skeleton_and_content_types.hpp>
namespace boost { namespace mpi {
-/**
- * @brief A proxy that requests that the skeleton of an object be
- * transmitted.
- *
- * The @c skeleton_proxy is a lightweight proxy object used to
- * indicate that the skeleton of an object, not the object itself,
- * should be transmitted. It can be used with the @c send and @c recv
- * operations of communicators or the @c broadcast collective. When a
- * @c skeleton_proxy is sent, Boost.MPI generates a description
- * containing the structure of the stored object. When that skeleton
- * is received, the receiving object is reshaped to match the
- * structure. Once the skeleton of an object as been transmitted, its
- * @c content can be transmitted separately (often several times)
- * without changing the structure of the object.
- */
-template <class T>
-struct BOOST_MPI_DECL skeleton_proxy
-{
- /**
- * Constructs a @c skeleton_proxy that references object @p x.
- *
- * @param x the object whose structure will be transmitted or
- * altered.
- */
- skeleton_proxy(T& x)
- : object(x)
- {}
-
- T& object;
-};
-
-/**
- * @brief Create a skeleton proxy object.
- *
- * This routine creates an instance of the skeleton_proxy class. It
- * will typically be used when calling @c send, @c recv, or @c
- * broadcast, to indicate that only the skeleton (structure) of an
- * object should be transmitted and not its contents.
- *
- * @param x the object whose structure will be transmitted.
- *
- * @returns a skeleton_proxy object referencing @p x
- */
-template <class T>
-inline const skeleton_proxy<T> skeleton(T& x)
-{
- return skeleton_proxy<T>(x);
-}
-
-namespace detail {
- /// @brief a class holding an MPI datatype
- /// INTERNAL ONLY
- /// the type is freed upon destruction
- class BOOST_MPI_DECL mpi_datatype_holder : public boost::noncopyable
- {
- public:
- mpi_datatype_holder()
- : is_committed(false)
- {}
-
- mpi_datatype_holder(MPI_Datatype t, bool committed = true)
- : d(t)
- , is_committed(committed)
- {}
-
- void commit()
- {
- BOOST_MPI_CHECK_RESULT(MPI_Type_commit,(&d));
- is_committed=true;
- }
-
- MPI_Datatype get_mpi_datatype() const
- {
- return d;
- }
-
- ~mpi_datatype_holder()
- {
- int finalized=0;
- BOOST_MPI_CHECK_RESULT(MPI_Finalized,(&finalized));
- if (!finalized && is_committed)
- BOOST_MPI_CHECK_RESULT(MPI_Type_free,(&d));
- }
-
- private:
- MPI_Datatype d;
- bool is_committed;
- };
-} // end namespace detail
-
-/** @brief A proxy object that transfers the content of an object
- * without its structure.
- *
- * The @c content class indicates that Boost.MPI should transmit or
- * receive the content of an object, but without any information
- * about the structure of the object. It is only meaningful to
- * transmit the content of an object after the receiver has already
- * received the skeleton for the same object.
- *
- * Most users will not use @c content objects directly. Rather, they
- * will invoke @c send, @c recv, or @c broadcast operations using @c
- * get_content().
- */
-class BOOST_MPI_DECL content
-{
-public:
- /**
- * Constructs an empty @c content object. This object will not be
- * useful for any Boost.MPI operations until it is reassigned.
- */
- content() {}
-
- /**
- * This routine initializes the @c content object with an MPI data
- * type that refers to the content of an object without its structure.
- *
- * @param d the MPI data type referring to the content of the object.
- *
- * @param committed @c true indicates that @c MPI_Type_commit has
- * already been excuted for the data type @p d.
- */
- content(MPI_Datatype d, bool committed=true)
- : holder(new detail::mpi_datatype_holder(d,committed))
- {}
-
- /**
- * Replace the MPI data type referencing the content of an object.
- *
- * @param d the new MPI data type referring to the content of the
- * object.
- *
- * @returns *this
- */
- const content& operator=(MPI_Datatype d)
- {
- holder.reset(new detail::mpi_datatype_holder(d));
- return *this;
- }
-
- /**
- * Retrieve the MPI data type that refers to the content of the
- * object.
- *
- * @returns the MPI data type, which should only be transmitted or
- * received using @c MPI_BOTTOM as the address.
- */
- MPI_Datatype get_mpi_datatype() const
- {
- return holder->get_mpi_datatype();
- }
-
- /**
- * Commit the MPI data type referring to the content of the
- * object.
- */
- void commit()
- {
- holder->commit();
- }
-
-private:
- boost::shared_ptr<detail::mpi_datatype_holder> holder;
-};
-
-/** @brief Returns the content of an object, suitable for transmission
- * via Boost.MPI.
- *
- * The function creates an absolute MPI datatype for the object,
- * where all offsets are counted from the address 0 (a.k.a. @c
- * MPI_BOTTOM) instead of the address @c &x of the object. This
- * allows the creation of MPI data types for complex data structures
- * containing pointers, such as linked lists or trees.
- *
- * The disadvantage, compared to relative MPI data types is that for
- * each object a new MPI data type has to be created.
- *
- * The contents of an object can only be transmitted when the
- * receiver already has an object with the same structure or shape as
- * the sender. To accomplish this, first transmit the skeleton of the
- * object using, e.g., @c skeleton() or @c skeleton_proxy.
- *
- * The type @c T has to allow creation of an absolute MPI data type
- * (content).
- *
- * @param x the object for which the content will be transmitted.
- *
- * @returns the content of the object @p x, which can be used for
- * transmission via @c send, @c recv, or @c broadcast.
- */
-template <class T> const content get_content(const T& x);
-
-/** @brief An archiver that reconstructs a data structure based on the
- * binary skeleton stored in a buffer.
- *
- * The @c packed_skeleton_iarchive class is an Archiver (as in the
- * Boost.Serialization library) that can construct the the shape of a
- * data structure based on a binary skeleton stored in a buffer. The
- * @c packed_skeleton_iarchive is typically used by the receiver of a
- * skeleton, to prepare a data structure that will eventually receive
- * content separately.
- *
- * Users will not generally need to use @c packed_skeleton_iarchive
- * directly. Instead, use @c skeleton or @c get_skeleton.
- */
-class BOOST_MPI_DECL packed_skeleton_iarchive
- : public detail::ignore_iprimitive,
- public detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>
-{
-public:
- /**
- * Construct a @c packed_skeleton_iarchive for the given
- * communicator.
- *
- * @param comm The communicator over which this archive will be
- * transmitted.
- *
- * @param flags Control the serialization of the skeleton. Refer to
- * the Boost.Serialization documentation before changing the
- * default flags.
- */
- packed_skeleton_iarchive(MPI_Comm const & comm,
- unsigned int flags = boost::archive::no_header)
- : detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>(skeleton_archive_)
- , skeleton_archive_(comm,flags)
- {}
-
- /**
- * Construct a @c packed_skeleton_iarchive that unpacks a skeleton
- * from the given @p archive.
- *
- * @param archive the archive from which the skeleton will be
- * unpacked.
- *
- */
- explicit packed_skeleton_iarchive(packed_iarchive & archive)
- : detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>(archive)
- , skeleton_archive_(MPI_COMM_WORLD, boost::archive::no_header)
- {}
-
- /**
- * Retrieve the archive corresponding to this skeleton.
- */
- const packed_iarchive& get_skeleton() const
- {
- return this->implementation_archive;
- }
-
- /**
- * Retrieve the archive corresponding to this skeleton.
- */
- packed_iarchive& get_skeleton()
- {
- return this->implementation_archive;
- }
-
-private:
- /// Store the actual archive that holds the structure, unless the
- /// user overrides this with their own archive.
- packed_iarchive skeleton_archive_;
-};
-
-/** @brief An archiver that records the binary skeleton of a data
- * structure into a buffer.
- *
- * The @c packed_skeleton_oarchive class is an Archiver (as in the
- * Boost.Serialization library) that can record the shape of a data
- * structure (called the "skeleton") into a binary representation
- * stored in a buffer. The @c packed_skeleton_oarchive is typically
- * used by the send of a skeleton, to pack the skeleton of a data
- * structure for transmission separately from the content.
- *
- * Users will not generally need to use @c packed_skeleton_oarchive
- * directly. Instead, use @c skeleton or @c get_skeleton.
- */
-class BOOST_MPI_DECL packed_skeleton_oarchive
- : public detail::ignore_oprimitive,
- public detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>
-{
-public:
- /**
- * Construct a @c packed_skeleton_oarchive for the given
- * communicator.
- *
- * @param comm The communicator over which this archive will be
- * transmitted.
- *
- * @param flags Control the serialization of the skeleton. Refer to
- * the Boost.Serialization documentation before changing the
- * default flags.
- */
- packed_skeleton_oarchive(MPI_Comm const & comm,
- unsigned int flags = boost::archive::no_header)
- : detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>(skeleton_archive_)
- , skeleton_archive_(comm,flags)
- {}
-
- /**
- * Construct a @c packed_skeleton_oarchive that packs a skeleton
- * into the given @p archive.
- *
- * @param archive the archive to which the skeleton will be packed.
- *
- */
- explicit packed_skeleton_oarchive(packed_oarchive & archive)
- : detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>(archive)
- , skeleton_archive_(MPI_COMM_WORLD, boost::archive::no_header)
- {}
-
- /**
- * Retrieve the archive corresponding to this skeleton.
- */
- const packed_oarchive& get_skeleton() const
- {
- return this->implementation_archive;
- }
-
-private:
- /// Store the actual archive that holds the structure.
- packed_oarchive skeleton_archive_;
-};
-
namespace detail {
typedef boost::mpi::detail::forward_skeleton_oarchive<boost::mpi::packed_skeleton_oarchive,boost::mpi::packed_oarchive> type1;
typedef boost::mpi::detail::forward_skeleton_iarchive<boost::mpi::packed_skeleton_iarchive,boost::mpi::packed_iarchive> type2;
diff --git a/boost/mpi/skeleton_and_content_types.hpp b/boost/mpi/skeleton_and_content_types.hpp
new file mode 100644
index 0000000000..825f2dfaee
--- /dev/null
+++ b/boost/mpi/skeleton_and_content_types.hpp
@@ -0,0 +1,363 @@
+// (C) Copyright 2005 Matthias Troyer
+// (C) Copyright 2006 Douglas Gregor <doug.gregor -at gmail.com>
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Matthias Troyer
+// Douglas Gregor
+
+/** @file skeleton_and_content.hpp
+ *
+ * This header provides facilities that allow the structure of data
+ * types (called the "skeleton") to be transmitted and received
+ * separately from the content stored in those data types. These
+ * facilities are useful when the data in a stable data structure
+ * (e.g., a mesh or a graph) will need to be transmitted
+ * repeatedly. In this case, transmitting the skeleton only once
+ * saves both communication effort (it need not be sent again) and
+ * local computation (serialization need only be performed once for
+ * the content).
+ */
+#ifndef BOOST_MPI_SKELETON_AND_CONTENT_TYPES_HPP
+#define BOOST_MPI_SKELETON_AND_CONTENT_TYPES_HPP
+
+#include <boost/mpi/config.hpp>
+#include <boost/archive/detail/auto_link_archive.hpp>
+#include <boost/mpi/packed_iarchive.hpp>
+#include <boost/mpi/packed_oarchive.hpp>
+#include <boost/mpi/detail/forward_skeleton_iarchive.hpp>
+#include <boost/mpi/detail/forward_skeleton_oarchive.hpp>
+#include <boost/mpi/detail/ignore_iprimitive.hpp>
+#include <boost/mpi/detail/ignore_oprimitive.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/archive/detail/register_archive.hpp>
+
+namespace boost { namespace mpi {
+
+/**
+ * @brief A proxy that requests that the skeleton of an object be
+ * transmitted.
+ *
+ * The @c skeleton_proxy is a lightweight proxy object used to
+ * indicate that the skeleton of an object, not the object itself,
+ * should be transmitted. It can be used with the @c send and @c recv
+ * operations of communicators or the @c broadcast collective. When a
+ * @c skeleton_proxy is sent, Boost.MPI generates a description
+ * containing the structure of the stored object. When that skeleton
+ * is received, the receiving object is reshaped to match the
+ * structure. Once the skeleton of an object as been transmitted, its
+ * @c content can be transmitted separately (often several times)
+ * without changing the structure of the object.
+ */
+template <class T>
+struct BOOST_MPI_DECL skeleton_proxy
+{
+ /**
+ * Constructs a @c skeleton_proxy that references object @p x.
+ *
+ * @param x the object whose structure will be transmitted or
+ * altered.
+ */
+ skeleton_proxy(T& x)
+ : object(x)
+ {}
+
+ T& object;
+};
+
+/**
+ * @brief Create a skeleton proxy object.
+ *
+ * This routine creates an instance of the skeleton_proxy class. It
+ * will typically be used when calling @c send, @c recv, or @c
+ * broadcast, to indicate that only the skeleton (structure) of an
+ * object should be transmitted and not its contents.
+ *
+ * @param x the object whose structure will be transmitted.
+ *
+ * @returns a skeleton_proxy object referencing @p x
+ */
+template <class T>
+inline const skeleton_proxy<T> skeleton(T& x)
+{
+ return skeleton_proxy<T>(x);
+}
+
+namespace detail {
+ /// @brief a class holding an MPI datatype
+ /// INTERNAL ONLY
+ /// the type is freed upon destruction
+ class BOOST_MPI_DECL mpi_datatype_holder : public boost::noncopyable
+ {
+ public:
+ mpi_datatype_holder()
+ : is_committed(false)
+ {}
+
+ mpi_datatype_holder(MPI_Datatype t, bool committed = true)
+ : d(t)
+ , is_committed(committed)
+ {}
+
+ void commit()
+ {
+ BOOST_MPI_CHECK_RESULT(MPI_Type_commit,(&d));
+ is_committed=true;
+ }
+
+ MPI_Datatype get_mpi_datatype() const
+ {
+ return d;
+ }
+
+ ~mpi_datatype_holder()
+ {
+ int finalized=0;
+ BOOST_MPI_CHECK_RESULT(MPI_Finalized,(&finalized));
+ if (!finalized && is_committed)
+ BOOST_MPI_CHECK_RESULT(MPI_Type_free,(&d));
+ }
+
+ private:
+ MPI_Datatype d;
+ bool is_committed;
+ };
+} // end namespace detail
+
+/** @brief A proxy object that transfers the content of an object
+ * without its structure.
+ *
+ * The @c content class indicates that Boost.MPI should transmit or
+ * receive the content of an object, but without any information
+ * about the structure of the object. It is only meaningful to
+ * transmit the content of an object after the receiver has already
+ * received the skeleton for the same object.
+ *
+ * Most users will not use @c content objects directly. Rather, they
+ * will invoke @c send, @c recv, or @c broadcast operations using @c
+ * get_content().
+ */
+class BOOST_MPI_DECL content
+{
+public:
+ /**
+ * Constructs an empty @c content object. This object will not be
+ * useful for any Boost.MPI operations until it is reassigned.
+ */
+ content() {}
+
+ /**
+ * This routine initializes the @c content object with an MPI data
+ * type that refers to the content of an object without its structure.
+ *
+ * @param d the MPI data type referring to the content of the object.
+ *
+ * @param committed @c true indicates that @c MPI_Type_commit has
+ * already been excuted for the data type @p d.
+ */
+ content(MPI_Datatype d, bool committed=true)
+ : holder(new detail::mpi_datatype_holder(d,committed))
+ {}
+
+ /**
+ * Replace the MPI data type referencing the content of an object.
+ *
+ * @param d the new MPI data type referring to the content of the
+ * object.
+ *
+ * @returns *this
+ */
+ const content& operator=(MPI_Datatype d)
+ {
+ holder.reset(new detail::mpi_datatype_holder(d));
+ return *this;
+ }
+
+ /**
+ * Retrieve the MPI data type that refers to the content of the
+ * object.
+ *
+ * @returns the MPI data type, which should only be transmitted or
+ * received using @c MPI_BOTTOM as the address.
+ */
+ MPI_Datatype get_mpi_datatype() const
+ {
+ return holder->get_mpi_datatype();
+ }
+
+ /**
+ * Commit the MPI data type referring to the content of the
+ * object.
+ */
+ void commit()
+ {
+ holder->commit();
+ }
+
+private:
+ boost::shared_ptr<detail::mpi_datatype_holder> holder;
+};
+
+/** @brief Returns the content of an object, suitable for transmission
+ * via Boost.MPI.
+ *
+ * The function creates an absolute MPI datatype for the object,
+ * where all offsets are counted from the address 0 (a.k.a. @c
+ * MPI_BOTTOM) instead of the address @c &x of the object. This
+ * allows the creation of MPI data types for complex data structures
+ * containing pointers, such as linked lists or trees.
+ *
+ * The disadvantage, compared to relative MPI data types is that for
+ * each object a new MPI data type has to be created.
+ *
+ * The contents of an object can only be transmitted when the
+ * receiver already has an object with the same structure or shape as
+ * the sender. To accomplish this, first transmit the skeleton of the
+ * object using, e.g., @c skeleton() or @c skeleton_proxy.
+ *
+ * The type @c T has to allow creation of an absolute MPI data type
+ * (content).
+ *
+ * @param x the object for which the content will be transmitted.
+ *
+ * @returns the content of the object @p x, which can be used for
+ * transmission via @c send, @c recv, or @c broadcast.
+ */
+template <class T> const content get_content(const T& x);
+
+/** @brief An archiver that reconstructs a data structure based on the
+ * binary skeleton stored in a buffer.
+ *
+ * The @c packed_skeleton_iarchive class is an Archiver (as in the
+ * Boost.Serialization library) that can construct the the shape of a
+ * data structure based on a binary skeleton stored in a buffer. The
+ * @c packed_skeleton_iarchive is typically used by the receiver of a
+ * skeleton, to prepare a data structure that will eventually receive
+ * content separately.
+ *
+ * Users will not generally need to use @c packed_skeleton_iarchive
+ * directly. Instead, use @c skeleton or @c get_skeleton.
+ */
+class BOOST_MPI_DECL packed_skeleton_iarchive
+ : public detail::ignore_iprimitive,
+ public detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>
+{
+public:
+ /**
+ * Construct a @c packed_skeleton_iarchive for the given
+ * communicator.
+ *
+ * @param comm The communicator over which this archive will be
+ * transmitted.
+ *
+ * @param flags Control the serialization of the skeleton. Refer to
+ * the Boost.Serialization documentation before changing the
+ * default flags.
+ */
+ packed_skeleton_iarchive(MPI_Comm const & comm,
+ unsigned int flags = boost::archive::no_header)
+ : detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>(skeleton_archive_)
+ , skeleton_archive_(comm,flags)
+ {}
+
+ /**
+ * Construct a @c packed_skeleton_iarchive that unpacks a skeleton
+ * from the given @p archive.
+ *
+ * @param archive the archive from which the skeleton will be
+ * unpacked.
+ *
+ */
+ explicit packed_skeleton_iarchive(packed_iarchive & archive)
+ : detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>(archive)
+ , skeleton_archive_(MPI_COMM_WORLD, boost::archive::no_header)
+ {}
+
+ /**
+ * Retrieve the archive corresponding to this skeleton.
+ */
+ const packed_iarchive& get_skeleton() const
+ {
+ return this->implementation_archive;
+ }
+
+ /**
+ * Retrieve the archive corresponding to this skeleton.
+ */
+ packed_iarchive& get_skeleton()
+ {
+ return this->implementation_archive;
+ }
+
+private:
+ /// Store the actual archive that holds the structure, unless the
+ /// user overrides this with their own archive.
+ packed_iarchive skeleton_archive_;
+};
+
+/** @brief An archiver that records the binary skeleton of a data
+ * structure into a buffer.
+ *
+ * The @c packed_skeleton_oarchive class is an Archiver (as in the
+ * Boost.Serialization library) that can record the shape of a data
+ * structure (called the "skeleton") into a binary representation
+ * stored in a buffer. The @c packed_skeleton_oarchive is typically
+ * used by the send of a skeleton, to pack the skeleton of a data
+ * structure for transmission separately from the content.
+ *
+ * Users will not generally need to use @c packed_skeleton_oarchive
+ * directly. Instead, use @c skeleton or @c get_skeleton.
+ */
+class BOOST_MPI_DECL packed_skeleton_oarchive
+ : public detail::ignore_oprimitive,
+ public detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>
+{
+public:
+ /**
+ * Construct a @c packed_skeleton_oarchive for the given
+ * communicator.
+ *
+ * @param comm The communicator over which this archive will be
+ * transmitted.
+ *
+ * @param flags Control the serialization of the skeleton. Refer to
+ * the Boost.Serialization documentation before changing the
+ * default flags.
+ */
+ packed_skeleton_oarchive(MPI_Comm const & comm,
+ unsigned int flags = boost::archive::no_header)
+ : detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>(skeleton_archive_)
+ , skeleton_archive_(comm,flags)
+ {}
+
+ /**
+ * Construct a @c packed_skeleton_oarchive that packs a skeleton
+ * into the given @p archive.
+ *
+ * @param archive the archive to which the skeleton will be packed.
+ *
+ */
+ explicit packed_skeleton_oarchive(packed_oarchive & archive)
+ : detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>(archive)
+ , skeleton_archive_(MPI_COMM_WORLD, boost::archive::no_header)
+ {}
+
+ /**
+ * Retrieve the archive corresponding to this skeleton.
+ */
+ const packed_oarchive& get_skeleton() const
+ {
+ return this->implementation_archive;
+ }
+
+private:
+ /// Store the actual archive that holds the structure.
+ packed_oarchive skeleton_archive_;
+};
+
+
+} } // end namespace boost::mpi
+
+#endif // BOOST_MPI_SKELETON_AND_CONTENT_TYPES_HPP
diff --git a/boost/mpi/status.hpp b/boost/mpi/status.hpp
index d444faa41d..326c0a8c08 100644
--- a/boost/mpi/status.hpp
+++ b/boost/mpi/status.hpp
@@ -14,6 +14,7 @@
#include <boost/mpi/config.hpp>
#include <boost/optional.hpp>
+#include <boost/mpl/bool.hpp>
namespace boost { namespace mpi {
diff --git a/boost/mpl/if.hpp b/boost/mpl/if.hpp
index b6bdf6c692..3b0ae19228 100644
--- a/boost/mpl/if.hpp
+++ b/boost/mpl/if.hpp
@@ -46,7 +46,7 @@ struct if_c<false,T1,T2>
};
// agurt, 05/sep/04: nondescriptive parameter names for the sake of DigitalMars
-// (and possibly MWCW < 8.0); see http://article.gmane.org/gmane.comp.lib.boost.devel/108959
+// (and possibly MWCW < 8.0); see https://lists.boost.org/Archives/boost/2004/09/71383.php
template<
typename BOOST_MPL_AUX_NA_PARAM(T1)
, typename BOOST_MPL_AUX_NA_PARAM(T2)
diff --git a/boost/multi_array.hpp b/boost/multi_array.hpp
index 46979ac7eb..5043eccbf8 100644
--- a/boost/multi_array.hpp
+++ b/boost/multi_array.hpp
@@ -33,7 +33,7 @@
#include "boost/multi_array/subarray.hpp"
#include "boost/multi_array/multi_array_ref.hpp"
#include "boost/multi_array/algorithm.hpp"
-#include "boost/multi_array/allocators.hpp"
+#include "boost/core/alloc_construct.hpp"
#include "boost/core/empty_value.hpp"
#include "boost/array.hpp"
#include "boost/mpl/if.hpp"
@@ -545,12 +545,12 @@ private:
base_ = allocator().allocate(this->num_elements());
this->set_base_ptr(base_);
allocated_elements_ = this->num_elements();
- detail::multi_array::construct(allocator(),base_,base_+allocated_elements_);
+ boost::alloc_construct_n(allocator(),base_,allocated_elements_);
}
void deallocate_space() {
if(base_) {
- detail::multi_array::destroy(allocator(),base_,base_+allocated_elements_);
+ boost::alloc_destroy_n(allocator(),base_,allocated_elements_);
allocator().deallocate(base_,allocated_elements_);
}
}
diff --git a/boost/multi_array/allocators.hpp b/boost/multi_array/allocators.hpp
deleted file mode 100644
index 469146464a..0000000000
--- a/boost/multi_array/allocators.hpp
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2018 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_MULTI_ARRAY_ALLOCATORS_HPP
-#define BOOST_MULTI_ARRAY_ALLOCATORS_HPP
-
-#include <boost/config.hpp>
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-#include <memory>
-#else
-#include <new>
-#endif
-
-namespace boost {
-namespace detail {
-namespace multi_array {
-
-template<class A, class T>
-inline void destroy(A& allocator, T* ptr, T* end)
-{
- for (; ptr != end; ++ptr) {
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- std::allocator_traits<A>::destroy(allocator,ptr);
-#else
- ptr->~T();
-#endif
- }
-}
-
-template<class A, class T>
-inline void construct(A& allocator, T* ptr)
-{
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- std::allocator_traits<A>::construct(allocator,ptr);
-#else
- ::new(static_cast<void*>(ptr)) T();
-#endif
-}
-
-#if !defined(BOOST_NO_EXCEPTIONS)
-template<class A, class T>
-inline void construct(A& allocator, T* ptr, T* end)
-{
- T* start = ptr;
- try {
- for (; ptr != end; ++ptr) {
- boost::detail::multi_array::construct(allocator,ptr);
- }
- } catch (...) {
- boost::detail::multi_array::destroy(allocator,start,ptr);
- throw;
- }
-}
-#else
-template<class A, class T>
-inline void construct(A& allocator, T* ptr, T* end)
-{
- for (; ptr != end; ++ptr) {
- boost::detail::multi_array::construct(allocator,ptr);
- }
-}
-#endif
-
-} // multi_array
-} // detail
-} // boost
-
-#endif
diff --git a/boost/multi_index/detail/is_function.hpp b/boost/multi_index/detail/is_function.hpp
new file mode 100644
index 0000000000..765f963ee2
--- /dev/null
+++ b/boost/multi_index/detail/is_function.hpp
@@ -0,0 +1,52 @@
+/* Copyright 2003-2019 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.
+ */
+
+#ifndef BOOST_MULTI_INDEX_DETAIL_IS_FUNCTION_HPP
+#define BOOST_MULTI_INDEX_DETAIL_IS_FUNCTION_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
+#include <boost/detail/workaround.hpp>
+
+#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)||\
+ BOOST_WORKAROUND(_LIBCPP_VERSION,<30700)||\
+ BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40802)
+/* libc++: std::is_function<void() const> fails,
+ * https://bugs.llvm.org/show_bug.cgi?id=20084
+ *
+ * libstdc++-v3: std::is_function does not support ref-qualified function types,
+ * https://github.com/gcc-mirror/gcc/commit/
+ * 2fa630fb50ba29d8e891c52a75aaec261b07874e#
+ * diff-6547f965a8d66bf35a6388fcf404aaa3
+ */
+
+#include <boost/type_traits/is_function.hpp>
+
+namespace boost{namespace multi_index{namespace detail{
+
+template<typename T>
+struct is_function:boost::is_function<T>{};
+
+}}} /* namespace boost::multi_index::detail */
+
+#else
+
+#include <type_traits>
+
+namespace boost{namespace multi_index{namespace detail{
+
+template<typename T>
+struct is_function:std::is_function<T>{};
+
+}}} /* namespace boost::multi_index::detail */
+
+#endif
+#endif
diff --git a/boost/multi_index/key.hpp b/boost/multi_index/key.hpp
index 48a418ac53..e442c6e8d0 100644
--- a/boost/multi_index/key.hpp
+++ b/boost/multi_index/key.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2003-2018 Joaquin M Lopez Munoz.
+/* Copyright 2003-2019 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)
@@ -24,6 +24,8 @@
#define BOOST_MULTI_INDEX_KEY_SUPPORTED
+#include <boost/multi_index/detail/is_function.hpp>
+#include <boost/preprocessor/facilities/empty.hpp>
#include <type_traits>
namespace boost{
@@ -40,28 +42,33 @@ struct typed_key_impl;
template<typename Class,typename Type,Type Class::*PtrToMember>
struct typed_key_impl<
Type Class::*,PtrToMember,
- typename std::enable_if<!std::is_function<Type>::value>::type
+ typename std::enable_if<!is_function<Type>::value>::type
>
{
using value_type=Class;
using type=member<Class,Type,PtrToMember>;
};
-template<
- typename Class,typename Type,Type (Class::*PtrToMemberFunction)()const
->
-struct typed_key_impl<Type (Class::*)()const,PtrToMemberFunction>
-{
- using value_type=Class;
- using type=const_mem_fun<Class,Type,PtrToMemberFunction>;
+#define BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(qualifier,extractor) \
+template< \
+ typename Class,typename Type,Type (Class::*PtrToMemberFunction)()qualifier \
+> \
+struct typed_key_impl<Type (Class::*)()qualifier,PtrToMemberFunction> \
+{ \
+ using value_type=Class; \
+ using type=extractor<Class,Type,PtrToMemberFunction>; \
};
-template<typename Class,typename Type,Type (Class::*PtrToMemberFunction)()>
-struct typed_key_impl<Type (Class::*)(),PtrToMemberFunction>
-{
- using value_type=Class;
- using type=mem_fun<Class,Type,PtrToMemberFunction>;
-};
+BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL( ,mem_fun)
+BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const ,const_mem_fun)
+BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(volatile ,volatile_mem_fun)
+BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const volatile ,cv_mem_fun)
+BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(& ,ref_mem_fun)
+BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const& ,cref_mem_fun)
+BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(volatile& ,vref_mem_fun)
+BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const volatile& ,cvref_mem_fun)
+
+#undef BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
struct typed_key_impl<Type (*)(Value),PtrToFunction>
@@ -70,11 +77,48 @@ struct typed_key_impl<Type (*)(Value),PtrToFunction>
using type=global_fun<Value,Type,PtrToFunction>;
};
+template<typename T>
+struct remove_noexcept{using type=T;};
+
+#define BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(qualifier) \
+template<typename R,typename C,typename... Args> \
+struct remove_noexcept<R(C::*)(Args...)qualifier noexcept> \
+ {using type=R(C::*)(Args...)qualifier;}; \
+ \
+template<typename R,typename C,typename... Args> \
+struct remove_noexcept<R(C::*)(Args...,...)qualifier noexcept> \
+ {using type=R(C::*)(Args...,...)qualifier;};
+
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(BOOST_PP_EMPTY())
+ /* VS warns without dummy arg */
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const)
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(volatile)
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const volatile)
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(&)
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const&)
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(volatile&)
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const volatile&)
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(&&)
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const&&)
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(volatile&&)
+BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const volatile&&)
+
+#undef BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT
+
+template<typename R,typename... Args>
+struct remove_noexcept<R(*)(Args...)noexcept>{using type=R(*)(Args...);};
+template<typename R,typename... Args>
+struct remove_noexcept<R(*)(Args...,...)noexcept>
+ {using type=R(*)(Args...,...);};
+
+template<typename T>
+using remove_noexcept_t=typename remove_noexcept<T>::type;
+
template<auto... Keys>
struct key_impl;
template<auto Key>
-struct key_impl<Key>:typed_key_impl<decltype(Key),Key>{};
+struct key_impl<Key>:typed_key_impl<remove_noexcept_t<decltype(Key)>,Key>{};
template<typename... Ts>
struct least_generic;
diff --git a/boost/multi_index/mem_fun.hpp b/boost/multi_index/mem_fun.hpp
index 111c386c5f..aa116f0379 100644
--- a/boost/multi_index/mem_fun.hpp
+++ b/boost/multi_index/mem_fun.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2003-2015 Joaquin M Lopez Munoz.
+/* Copyright 2003-2019 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)
@@ -30,17 +30,30 @@ namespace multi_index{
/* mem_fun implements a read-only key extractor based on a given non-const
* member function of a class.
- * const_mem_fun does the same for const member functions.
- * Additionally, mem_fun and const_mem_fun are overloaded to support
- * referece_wrappers of T and "chained pointers" to T's. By chained pointer
- * to T we mean a type P such that, given a p of Type P
+ * Also, the following variations are provided:
+ * const_mem_fun: const member functions
+ * volatile_mem_fun: volatile member functions
+ * cv_mem_fun: const volatile member functions
+ * ref_mem_fun: ref-qualifed member functions (C++11)
+ * cref_mem_fun: const ref-qualifed member functions (C++11)
+ * vref_mem_fun: volatile ref-qualifed member functions (C++11)
+ * cvref_mem_fun: const volatile ref-qualifed member functions (C++11)
+ *
+ * All of these classes are overloaded to support boost::referece_wrappers
+ * of T and "chained pointers" to T's. By chained pointer to T we mean a type
+ * P such that, given a p of Type P
* *...n...*x is convertible to T&, for some n>=1.
* Examples of chained pointers are raw and smart pointers, iterators and
* arbitrary combinations of these (vg. T** or unique_ptr<T*>.)
*/
-template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()const>
-struct const_mem_fun
+namespace detail{
+
+template<
+ class Class,typename Type,
+ typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction
+>
+struct const_mem_fun_impl
{
typedef typename remove_reference<Type>::type result_type;
@@ -74,8 +87,11 @@ struct const_mem_fun
}
};
-template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()>
-struct mem_fun
+template<
+ class Class,typename Type,
+ typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction
+>
+struct mem_fun_impl
{
typedef typename remove_reference<Type>::type result_type;
@@ -104,6 +120,62 @@ struct mem_fun
}
};
+} /* namespace multi_index::detail */
+
+template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()const>
+struct const_mem_fun:detail::const_mem_fun_impl<
+ Class,Type,Type (Class::*)()const,PtrToMemberFunction
+>{};
+
+template<
+ class Class,typename Type,
+ Type (Class::*PtrToMemberFunction)()const volatile
+>
+struct cv_mem_fun:detail::const_mem_fun_impl<
+ Class,Type,Type (Class::*)()const volatile,PtrToMemberFunction
+>{};
+
+template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()>
+struct mem_fun:
+ detail::mem_fun_impl<Class,Type,Type (Class::*)(),PtrToMemberFunction>{};
+
+template<
+ class Class,typename Type,Type (Class::*PtrToMemberFunction)()volatile
+>
+struct volatile_mem_fun:detail::mem_fun_impl<
+ Class,Type,Type (Class::*)()volatile,PtrToMemberFunction
+>{};
+
+#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
+
+template<
+ class Class,typename Type,Type (Class::*PtrToMemberFunction)()const&
+>
+struct cref_mem_fun:detail::const_mem_fun_impl<
+ Class,Type,Type (Class::*)()const&,PtrToMemberFunction
+>{};
+
+template<
+ class Class,typename Type,
+ Type (Class::*PtrToMemberFunction)()const volatile&
+>
+struct cvref_mem_fun:detail::const_mem_fun_impl<
+ Class,Type,Type (Class::*)()const volatile&,PtrToMemberFunction
+>{};
+
+template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()&>
+struct ref_mem_fun:
+ detail::mem_fun_impl<Class,Type,Type (Class::*)()&,PtrToMemberFunction>{};
+
+template<
+ class Class,typename Type,Type (Class::*PtrToMemberFunction)()volatile&
+>
+struct vref_mem_fun:detail::mem_fun_impl<
+ Class,Type,Type (Class::*)()volatile&,PtrToMemberFunction
+>{};
+
+#endif
+
/* MSVC++ 6.0 has problems with const member functions as non-type template
* parameters, somehow it takes them as non-const. const_mem_fun_explicit
* workarounds this deficiency by accepting an extra type parameter that
@@ -119,7 +191,8 @@ struct mem_fun
template<
class Class,typename Type,
- typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction>
+ typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction
+>
struct const_mem_fun_explicit
{
typedef typename remove_reference<Type>::type result_type;
@@ -156,7 +229,8 @@ struct const_mem_fun_explicit
template<
class Class,typename Type,
- typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction>
+ typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction
+>
struct mem_fun_explicit
{
typedef typename remove_reference<Type>::type result_type;
diff --git a/boost/multiprecision/concepts/mp_number_archetypes.hpp b/boost/multiprecision/concepts/mp_number_archetypes.hpp
index 5e1051c888..30dca7d0c7 100644
--- a/boost/multiprecision/concepts/mp_number_archetypes.hpp
+++ b/boost/multiprecision/concepts/mp_number_archetypes.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MATH_CONCEPTS_ER_HPP
#define BOOST_MATH_CONCEPTS_ER_HPP
diff --git a/boost/multiprecision/cpp_bin_float.hpp b/boost/multiprecision/cpp_bin_float.hpp
index 3d8369500d..9161a9fa4c 100644
--- a/boost/multiprecision/cpp_bin_float.hpp
+++ b/boost/multiprecision/cpp_bin_float.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MATH_CPP_BIN_FLOAT_HPP
#define BOOST_MATH_CPP_BIN_FLOAT_HPP
diff --git a/boost/multiprecision/cpp_bin_float/io.hpp b/boost/multiprecision/cpp_bin_float/io.hpp
index 8a3faaa4ff..43b016a73d 100644
--- a/boost/multiprecision/cpp_bin_float/io.hpp
+++ b/boost/multiprecision/cpp_bin_float/io.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_BIN_FLOAT_IO_HPP
#define BOOST_MP_CPP_BIN_FLOAT_IO_HPP
diff --git a/boost/multiprecision/cpp_bin_float/transcendental.hpp b/boost/multiprecision/cpp_bin_float/transcendental.hpp
index 5c1842dc7e..654e6678d7 100644
--- a/boost/multiprecision/cpp_bin_float/transcendental.hpp
+++ b/boost/multiprecision/cpp_bin_float/transcendental.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MULTIPRECISION_CPP_BIN_FLOAT_TRANSCENDENTAL_HPP
#define BOOST_MULTIPRECISION_CPP_BIN_FLOAT_TRANSCENDENTAL_HPP
diff --git a/boost/multiprecision/cpp_dec_float.hpp b/boost/multiprecision/cpp_dec_float.hpp
index c09ddee5e3..113e70f0d6 100644
--- a/boost/multiprecision/cpp_dec_float.hpp
+++ b/boost/multiprecision/cpp_dec_float.hpp
@@ -1308,7 +1308,7 @@ cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, Expone
// the run-time.
//
// Book references:
- // http://www.jjj.de/pibook/pibook.html
+ // https://doi.org/10.1007/978-3-642-56735-3
// http://www.amazon.com/exec/obidos/tg/detail/-/3540665722/qid=1035535482/sr=8-7/ref=sr_8_7/104-3357872-6059916?v=glance&n=507846
static const boost::uint32_t double_digits10_minus_a_few = std::numeric_limits<double>::digits10 - 3;
@@ -1802,17 +1802,16 @@ std::string cpp_dec_float<Digits10, ExponentType, Allocator>::str(boost::intmax_
// Extract the remaining digits from cpp_dec_float<Digits10, ExponentType, Allocator> after the decimal point.
str = boost::lexical_cast<std::string>(data[0]);
+ std::stringstream ss;
// Extract all of the digits from cpp_dec_float<Digits10, ExponentType, Allocator>, beginning with the first data element.
for(std::size_t i = static_cast<std::size_t>(1u); i < number_of_elements; i++)
{
- std::stringstream ss;
-
ss << std::setw(static_cast<std::streamsize>(cpp_dec_float_elem_digits10))
<< std::setfill(static_cast<char>('0'))
<< data[i];
- str += ss.str();
}
+ str += ss.str();
bool have_leading_zeros = false;
diff --git a/boost/multiprecision/cpp_int.hpp b/boost/multiprecision/cpp_int.hpp
index 6af30fd9ec..de15600abb 100644
--- a/boost/multiprecision/cpp_int.hpp
+++ b/boost/multiprecision/cpp_int.hpp
@@ -1,7 +1,7 @@
//////////////////3/////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_HPP
#define BOOST_MP_CPP_INT_HPP
@@ -1577,11 +1577,12 @@ private:
typename base_type::local_limb_type v = *this->limbs();
result.assign(Bits / shift + (Bits % shift ? 1 : 0), '0');
std::string::difference_type pos = result.size() - 1;
+ char letter_a = f & std::ios_base::uppercase ? 'A' : 'a';
for(unsigned i = 0; i < Bits / shift; ++i)
{
char c = '0' + static_cast<char>(v & mask);
if(c > '9')
- c += 'A' - '9' - 1;
+ c += letter_a - '9' - 1;
result[pos--] = c;
v >>= shift;
}
@@ -1590,7 +1591,7 @@ private:
mask = static_cast<limb_type>((1u << (Bits % shift)) - 1);
char c = '0' + static_cast<char>(v & mask);
if(c > '9')
- c += 'A' - '9';
+ c += letter_a - '9';
result[pos] = c;
}
//
@@ -1602,7 +1603,7 @@ private:
result.erase(0, n);
if(f & std::ios_base::showbase)
{
- const char* pp = base == 8 ? "0" : "0x";
+ const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x";
result.insert(static_cast<std::string::size_type>(0), pp);
}
}
@@ -1662,11 +1663,12 @@ private:
cpp_int_backend t(*this);
result.assign(Bits / shift + ((Bits % shift) ? 1 : 0), '0');
std::string::difference_type pos = result.size() - 1;
+ char letter_a = f & std::ios_base::uppercase ? 'A' : 'a';
for(unsigned i = 0; i < Bits / shift; ++i)
{
char c = '0' + static_cast<char>(t.limbs()[0] & mask);
if(c > '9')
- c += 'A' - '9' - 1;
+ c += letter_a - '9' - 1;
result[pos--] = c;
eval_right_shift(t, shift);
}
@@ -1675,7 +1677,7 @@ private:
mask = static_cast<limb_type>((1u << (Bits % shift)) - 1);
char c = '0' + static_cast<char>(t.limbs()[0] & mask);
if(c > '9')
- c += 'A' - '9';
+ c += letter_a - '9';
result[pos] = c;
}
//
@@ -1687,7 +1689,7 @@ private:
result.erase(0, n);
if(f & std::ios_base::showbase)
{
- const char* pp = base == 8 ? "0" : "0x";
+ const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x";
result.insert(static_cast<std::string::size_type>(0), pp);
}
}
diff --git a/boost/multiprecision/cpp_int/add.hpp b/boost/multiprecision/cpp_int/add.hpp
index 3b769cd8b6..8da7e1d859 100644
--- a/boost/multiprecision/cpp_int/add.hpp
+++ b/boost/multiprecision/cpp_int/add.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
diff --git a/boost/multiprecision/cpp_int/bitwise.hpp b/boost/multiprecision/cpp_int/bitwise.hpp
index bb0eb59e66..307ff885be 100644
--- a/boost/multiprecision/cpp_int/bitwise.hpp
+++ b/boost/multiprecision/cpp_int/bitwise.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
diff --git a/boost/multiprecision/cpp_int/checked.hpp b/boost/multiprecision/cpp_int/checked.hpp
index cafe50ea49..b3d499a4d2 100644
--- a/boost/multiprecision/cpp_int/checked.hpp
+++ b/boost/multiprecision/cpp_int/checked.hpp
@@ -1,7 +1,7 @@
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_CHECKED_HPP
#define BOOST_MP_CPP_INT_CHECKED_HPP
diff --git a/boost/multiprecision/cpp_int/comparison.hpp b/boost/multiprecision/cpp_int/comparison.hpp
index 48a66fc2b2..cf58ee0b07 100644
--- a/boost/multiprecision/cpp_int/comparison.hpp
+++ b/boost/multiprecision/cpp_int/comparison.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
diff --git a/boost/multiprecision/cpp_int/cpp_int_config.hpp b/boost/multiprecision/cpp_int/cpp_int_config.hpp
index eb88f3da80..9dbebcf52b 100644
--- a/boost/multiprecision/cpp_int/cpp_int_config.hpp
+++ b/boost/multiprecision/cpp_int/cpp_int_config.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_CORE_HPP
#define BOOST_MP_CPP_INT_CORE_HPP
diff --git a/boost/multiprecision/cpp_int/divide.hpp b/boost/multiprecision/cpp_int/divide.hpp
index 81583ec384..2856d50bf6 100644
--- a/boost/multiprecision/cpp_int/divide.hpp
+++ b/boost/multiprecision/cpp_int/divide.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
diff --git a/boost/multiprecision/cpp_int/import_export.hpp b/boost/multiprecision/cpp_int/import_export.hpp
index 7bb916d4ce..9aad882b2e 100644
--- a/boost/multiprecision/cpp_int/import_export.hpp
+++ b/boost/multiprecision/cpp_int/import_export.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2015 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_IMPORT_EXPORT_HPP
#define BOOST_MP_CPP_INT_IMPORT_EXPORT_HPP
diff --git a/boost/multiprecision/cpp_int/limits.hpp b/boost/multiprecision/cpp_int/limits.hpp
index b19e1ebbe6..7b1e59e7ff 100644
--- a/boost/multiprecision/cpp_int/limits.hpp
+++ b/boost/multiprecision/cpp_int/limits.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
diff --git a/boost/multiprecision/cpp_int/literals.hpp b/boost/multiprecision/cpp_int/literals.hpp
index ce30fd8484..3eff00e186 100644
--- a/boost/multiprecision/cpp_int/literals.hpp
+++ b/boost/multiprecision/cpp_int/literals.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_LITERALS_HPP
#define BOOST_MP_CPP_INT_LITERALS_HPP
diff --git a/boost/multiprecision/cpp_int/misc.hpp b/boost/multiprecision/cpp_int/misc.hpp
index 0985c73f42..9398db5cd4 100644
--- a/boost/multiprecision/cpp_int/misc.hpp
+++ b/boost/multiprecision/cpp_int/misc.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
diff --git a/boost/multiprecision/cpp_int/multiply.hpp b/boost/multiprecision/cpp_int/multiply.hpp
index ac01812b5c..f94ca84d53 100644
--- a/boost/multiprecision/cpp_int/multiply.hpp
+++ b/boost/multiprecision/cpp_int/multiply.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
diff --git a/boost/multiprecision/cpp_int/serialize.hpp b/boost/multiprecision/cpp_int/serialize.hpp
index ad0031b9de..c1d1b91588 100644
--- a/boost/multiprecision/cpp_int/serialize.hpp
+++ b/boost/multiprecision/cpp_int/serialize.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_SERIALIZE_HPP
#define BOOST_MP_CPP_INT_SERIALIZE_HPP
diff --git a/boost/multiprecision/cpp_int/value_pack.hpp b/boost/multiprecision/cpp_int/value_pack.hpp
index 29d9562e04..4b4ac09334 100644
--- a/boost/multiprecision/cpp_int/value_pack.hpp
+++ b/boost/multiprecision/cpp_int/value_pack.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_CPP_INT_VP_HPP
#define BOOST_MP_CPP_INT_VP_HPP
diff --git a/boost/multiprecision/debug_adaptor.hpp b/boost/multiprecision/debug_adaptor.hpp
index 505bea1df1..09569cea58 100644
--- a/boost/multiprecision/debug_adaptor.hpp
+++ b/boost/multiprecision/debug_adaptor.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MATH_DEBUG_ADAPTER_HPP
#define BOOST_MATH_DEBUG_ADAPTER_HPP
@@ -422,7 +422,7 @@ inline void eval_bit_flip(const debug_adaptor<Backend>& arg, unsigned a)
NON_MEMBER_OP3(gcd, "gcd")
NON_MEMBER_OP3(lcm, "lcm")
-NON_MEMBER_OP4(powm, "powm");
+NON_MEMBER_OP4(powm, "powm")
/*********************************************************************
*
diff --git a/boost/multiprecision/detail/bitscan.hpp b/boost/multiprecision/detail/bitscan.hpp
index e6fd74ac37..e5d756ef7a 100644
--- a/boost/multiprecision/detail/bitscan.hpp
+++ b/boost/multiprecision/detail/bitscan.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Comparison operators for cpp_int_backend:
//
diff --git a/boost/multiprecision/detail/digits.hpp b/boost/multiprecision/detail/digits.hpp
index 8752f5b5b0..2badb5ed42 100644
--- a/boost/multiprecision/detail/digits.hpp
+++ b/boost/multiprecision/detail/digits.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_DIGITS_HPP
#define BOOST_MP_DIGITS_HPP
diff --git a/boost/multiprecision/detail/float_string_cvt.hpp b/boost/multiprecision/detail/float_string_cvt.hpp
index 9b5774f1af..8cb4ebe4a8 100644
--- a/boost/multiprecision/detail/float_string_cvt.hpp
+++ b/boost/multiprecision/detail/float_string_cvt.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// Generic routines for converting floating point values to and from decimal strings.
// Note that these use "naive" algorithms which result in rounding error - so they
diff --git a/boost/multiprecision/detail/generic_interconvert.hpp b/boost/multiprecision/detail/generic_interconvert.hpp
index 783ddca6e2..94c66428b2 100644
--- a/boost/multiprecision/detail/generic_interconvert.hpp
+++ b/boost/multiprecision/detail/generic_interconvert.hpp
@@ -194,13 +194,20 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
eval_subtract(f, term);
}
typedef typename To::exponent_type to_exponent;
- if((e > (std::numeric_limits<to_exponent>::max)()) || (e < (std::numeric_limits<to_exponent>::min)()))
+ if(e > (std::numeric_limits<to_exponent>::max)())
{
to = static_cast<const char*>("inf");
if(eval_get_sign(from) < 0)
to.negate();
return;
}
+ if (e < (std::numeric_limits<to_exponent>::min)())
+ {
+ to = ui_type(0);
+ if (eval_get_sign(from) < 0)
+ to.negate();
+ return;
+ }
eval_ldexp(to, to, static_cast<to_exponent>(e));
#ifdef BOOST_MSVC
#pragma warning(pop)
diff --git a/boost/multiprecision/detail/integer_ops.hpp b/boost/multiprecision/detail/integer_ops.hpp
index 4b1a9d8bae..a789681c96 100644
--- a/boost/multiprecision/detail/integer_ops.hpp
+++ b/boost/multiprecision/detail/integer_ops.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_INT_FUNC_HPP
#define BOOST_MP_INT_FUNC_HPP
diff --git a/boost/multiprecision/float128.hpp b/boost/multiprecision/float128.hpp
index dd216c66db..ce290723be 100644
--- a/boost/multiprecision/float128.hpp
+++ b/boost/multiprecision/float128.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2013 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_FLOAT128_HPP
#define BOOST_MP_FLOAT128_HPP
@@ -264,8 +264,7 @@ public:
std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
{
#ifndef BOOST_MP_USE_QUAD
- char buf[100];
- boost::scoped_array<char> buf2;
+ char buf[128];
std::string format = "%";
if(f & std::ios_base::showpos)
format += "+";
@@ -275,6 +274,7 @@ public:
if(digits == 0)
digits = 36;
format += "Q";
+
if(f & std::ios_base::scientific)
format += "e";
else if(f & std::ios_base::fixed)
@@ -282,11 +282,17 @@ public:
else
format += "g";
- int v = quadmath_snprintf (buf, 100, format.c_str(), digits, m_value);
+ int v;
+ if ((f & std::ios_base::scientific) && (f & std::ios_base::fixed) ) {
+ v = quadmath_snprintf (buf, sizeof buf, "%Qa", m_value);
+ } else {
+ v = quadmath_snprintf (buf, sizeof buf, format.c_str(), digits, m_value);
+ }
- if((v < 0) || (v >= 99))
+ if((v < 0) || (v >= 127))
{
int v_max = v;
+ boost::scoped_array<char> buf2;
buf2.reset(new char[v+3]);
v = quadmath_snprintf (&buf2[0], v_max + 3, format.c_str(), digits, m_value);
if(v >= v_max + 3)
diff --git a/boost/multiprecision/gmp.hpp b/boost/multiprecision/gmp.hpp
index 0f5800ed3d..a03b75b9c3 100644
--- a/boost/multiprecision/gmp.hpp
+++ b/boost/multiprecision/gmp.hpp
@@ -39,6 +39,7 @@
# define BOOST_MP_MPIR_VERSION 0
#endif
+#include <cctype>
#include <cmath>
#include <limits>
#include <climits>
@@ -1328,11 +1329,13 @@ struct gmp_int
std::string s = ps;
mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
(*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
-
+ if (f & std::ios_base::uppercase)
+ for (size_t i = 0; i < s.length(); ++i)
+ s[i] = std::toupper(s[i]);
if((base != 10) && (f & std::ios_base::showbase))
{
int pos = s[0] == '-' ? 1 : 0;
- const char* pp = base == 8 ? "0" : "0x";
+ const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x";
s.insert(static_cast<std::string::size_type>(pos), pp);
}
if((f & std::ios_base::showpos) && (s[0] != '-'))
diff --git a/boost/multiprecision/integer.hpp b/boost/multiprecision/integer.hpp
index e4c8bf8b6c..f2b43c320a 100644
--- a/boost/multiprecision/integer.hpp
+++ b/boost/multiprecision/integer.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_INTEGER_HPP
#define BOOST_MP_INTEGER_HPP
diff --git a/boost/multiprecision/logged_adaptor.hpp b/boost/multiprecision/logged_adaptor.hpp
index 596d13ed74..014a117d3e 100644
--- a/boost/multiprecision/logged_adaptor.hpp
+++ b/boost/multiprecision/logged_adaptor.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MATH_LOGGED_ADAPTER_HPP
#define BOOST_MATH_LOGGED_ADAPTER_HPP
diff --git a/boost/multiprecision/miller_rabin.hpp b/boost/multiprecision/miller_rabin.hpp
index 156f9b852b..6553588130 100644
--- a/boost/multiprecision/miller_rabin.hpp
+++ b/boost/multiprecision/miller_rabin.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_MR_HPP
#define BOOST_MP_MR_HPP
diff --git a/boost/multiprecision/mpc.hpp b/boost/multiprecision/mpc.hpp
index f188454849..100b56cf72 100644
--- a/boost/multiprecision/mpc.hpp
+++ b/boost/multiprecision/mpc.hpp
@@ -555,7 +555,7 @@ struct mpc_complex_backend<0> : public detail::mpc_complex_imp<0>
}
mpc_complex_backend& operator=(mpf_srcptr val)
{
- if (mpc_get_prec(data()) != mpf_get_prec(val))
+ if ((mp_bitcnt_t)mpc_get_prec(data()) != mpf_get_prec(val))
{
mpc_complex_backend t(val);
t.swap(*this);
diff --git a/boost/multiprecision/number.hpp b/boost/multiprecision/number.hpp
index 892996b397..db56167767 100644
--- a/boost/multiprecision/number.hpp
+++ b/boost/multiprecision/number.hpp
@@ -6,6 +6,7 @@
#ifndef BOOST_MATH_EXTENDED_REAL_HPP
#define BOOST_MATH_EXTENDED_REAL_HPP
+#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/mpl/max.hpp>
#include <boost/mpl/plus.hpp>
@@ -130,7 +131,8 @@ public:
//
// Attempt a generic interconvertion:
//
- detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(val);
+ detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard_1(val);
+ detail::scoped_default_precision<number<Other, ET> > precision_guard_2(val);
using detail::generic_interconvert;
generic_interconvert(backend(), val.backend(), number_category<Backend>(), number_category<Other>());
}
@@ -295,6 +297,7 @@ public:
//
using detail::generic_interconvert;
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v);
+ detail::scoped_default_precision<number<Other, ET> > precision_guard2(v);
//
// If the current precision of *this differs from that of value v, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
diff --git a/boost/multiprecision/random.hpp b/boost/multiprecision/random.hpp
index c6b7d34e03..c69fd94dea 100644
--- a/boost/multiprecision/random.hpp
+++ b/boost/multiprecision/random.hpp
@@ -3,7 +3,7 @@
// Copyright Steven Watanabe 2011
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MP_RANDOM_HPP
#define BOOST_MP_RANDOM_HPP
diff --git a/boost/multiprecision/rational_adaptor.hpp b/boost/multiprecision/rational_adaptor.hpp
index 860a43bfa8..9f33ec93ce 100644
--- a/boost/multiprecision/rational_adaptor.hpp
+++ b/boost/multiprecision/rational_adaptor.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2011 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MATH_RATIONAL_ADAPTER_HPP
#define BOOST_MATH_RATIONAL_ADAPTER_HPP
diff --git a/boost/multiprecision/tommath.hpp b/boost/multiprecision/tommath.hpp
index 86d0e8f211..74c00637c5 100644
--- a/boost/multiprecision/tommath.hpp
+++ b/boost/multiprecision/tommath.hpp
@@ -14,6 +14,7 @@
#include <boost/scoped_array.hpp>
#include <boost/functional/hash_fwd.hpp>
#include <tommath.h>
+#include <cctype>
#include <cmath>
#include <limits>
#include <climits>
@@ -311,10 +312,13 @@ struct tommath_int
boost::scoped_array<char> a(new char[s+1]);
detail::check_tommath_result(mp_toradix_n(const_cast< ::mp_int*>(&m_data), a.get(), base, s+1));
std::string result = a.get();
+ if (f & std::ios_base::uppercase)
+ for (size_t i = 0; i < result.length(); ++i)
+ result[i] = std::toupper(result[i]);
if((base != 10) && (f & std::ios_base::showbase))
{
int pos = result[0] == '-' ? 1 : 0;
- const char* pp = base == 8 ? "0" : "0x";
+ const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x";
result.insert(static_cast<std::string::size_type>(pos), pp);
}
if((f & std::ios_base::showpos) && (result[0] != '-'))
diff --git a/boost/multiprecision/traits/extract_exponent_type.hpp b/boost/multiprecision/traits/extract_exponent_type.hpp
index adb30d5436..28c52c2d06 100644
--- a/boost/multiprecision/traits/extract_exponent_type.hpp
+++ b/boost/multiprecision/traits/extract_exponent_type.hpp
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_MATH_EXTRACT_EXPONENT_HPP
#define BOOST_MATH_EXTRACT_EXPONENT_HPP
diff --git a/boost/numeric/conversion/converter_policies.hpp b/boost/numeric/conversion/converter_policies.hpp
index e7a5e67ce9..1619d64df6 100644
--- a/boost/numeric/conversion/converter_policies.hpp
+++ b/boost/numeric/conversion/converter_policies.hpp
@@ -12,6 +12,7 @@
#include <typeinfo> // for std::bad_cast
+#include <boost/config.hpp>
#include <boost/config/no_tr1/cmath.hpp> // for std::floor and std::ceil
#include <boost/throw_exception.hpp>
@@ -136,7 +137,7 @@ class bad_numeric_cast : public std::bad_cast
{
public:
- virtual const char * what() const throw()
+ virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
{ return "bad numeric conversion: overflow"; }
};
@@ -144,14 +145,14 @@ class negative_overflow : public bad_numeric_cast
{
public:
- virtual const char * what() const throw()
+ virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
{ return "bad numeric conversion: negative overflow"; }
};
class positive_overflow : public bad_numeric_cast
{
public:
- virtual const char * what() const throw()
+ virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
{ return "bad numeric conversion: positive overflow"; }
};
diff --git a/boost/numeric/interval/detail/x86gcc_rounding_control.hpp b/boost/numeric/interval/detail/x86gcc_rounding_control.hpp
index da5513b552..9cedab83db 100644
--- a/boost/numeric/interval/detail/x86gcc_rounding_control.hpp
+++ b/boost/numeric/interval/detail/x86gcc_rounding_control.hpp
@@ -15,7 +15,7 @@
# error This header only works with GNU CC.
#endif
-#ifndef __i386__
+#if !defined(__i386__) && !defined(__x86_64__)
# error This header only works on x86 CPUs.
#endif
diff --git a/boost/numeric/odeint.hpp b/boost/numeric/odeint.hpp
index e0100899ca..642e46fe55 100644
--- a/boost/numeric/odeint.hpp
+++ b/boost/numeric/odeint.hpp
@@ -51,6 +51,9 @@
#include <boost/numeric/odeint/stepper/adams_bashforth_moulton.hpp>
+#include <boost/numeric/odeint/stepper/adaptive_adams_bashforth_moulton.hpp>
+#include <boost/numeric/odeint/stepper/controlled_adams_bashforth_moulton.hpp>
+
#include <boost/numeric/odeint/stepper/implicit_euler.hpp>
#include <boost/numeric/odeint/stepper/rosenbrock4.hpp>
#include <boost/numeric/odeint/stepper/rosenbrock4_controller.hpp>
diff --git a/boost/numeric/odeint/algebra/multi_array_algebra.hpp b/boost/numeric/odeint/algebra/multi_array_algebra.hpp
index 0bc476e631..f0ae30e4f4 100644
--- a/boost/numeric/odeint/algebra/multi_array_algebra.hpp
+++ b/boost/numeric/odeint/algebra/multi_array_algebra.hpp
@@ -19,6 +19,8 @@
#define BOOST_NUMERIC_ODEINT_ALGEBRA_MULTI_ARRAY_ALGEBRA_HPP_DEFINED
+#include <boost/multi_array.hpp>
+
#include <boost/numeric/odeint/algebra/detail/for_each.hpp>
#include <boost/numeric/odeint/algebra/detail/norm_inf.hpp>
#include <boost/numeric/odeint/algebra/norm_result_type.hpp>
@@ -121,7 +123,7 @@ struct multi_array_algebra
{
detail::for_each15( s1.data() , s1.data() + s1.num_elements() , s2.data() , s3.data() , s4.data() , s5.data() , s6.data() , s7.data() , s8.data() , s9.data() , s10.data() , s11.data() , s12.data() , s13.data() , s14.data() , s15.data() , op );
}
-
+
template< typename S >
static typename norm_result_type<S>::type norm_inf( const S &s )
{
@@ -129,15 +131,11 @@ struct multi_array_algebra
}
};
-// template< class T , size_t N >
-// struct algebra_dispatcher< boost::array< T , N > >
-// {
-// typedef array_algebra algebra_type;
-// };
-
-
-
-
+template< class T , size_t N >
+struct algebra_dispatcher< boost::multi_array< T , N > >
+{
+ typedef multi_array_algebra algebra_type;
+};
} // namespace odeint
diff --git a/boost/numeric/odeint/algebra/vector_space_algebra.hpp b/boost/numeric/odeint/algebra/vector_space_algebra.hpp
index 17ff007eef..450a015acd 100644
--- a/boost/numeric/odeint/algebra/vector_space_algebra.hpp
+++ b/boost/numeric/odeint/algebra/vector_space_algebra.hpp
@@ -30,7 +30,7 @@ namespace odeint {
/*
* This class template has to be overload in order to call vector_space_algebra::norm_inf
*/
-template< class State > struct vector_space_norm_inf;
+template< class State, class Enabler = void > struct vector_space_norm_inf;
/*
* Example: instantiation for sole doubles and complex
diff --git a/boost/numeric/odeint/external/eigen/eigen_algebra.hpp b/boost/numeric/odeint/external/eigen/eigen_algebra.hpp
index b4ee5c3b1f..3783cd814c 100644
--- a/boost/numeric/odeint/external/eigen/eigen_algebra.hpp
+++ b/boost/numeric/odeint/external/eigen/eigen_algebra.hpp
@@ -25,42 +25,36 @@
// from odeint
// (that is, it lets odeint treat the eigen matrices correctly, knowing
// how to add, multiply, compute the norm, etc)
-
namespace Eigen {
-
template<typename D>
inline const
-typename Eigen::CwiseUnaryOp<
- typename Eigen::internal::scalar_add_op<
- typename Eigen::internal::traits<D>::Scalar>,
- const D >
+typename Eigen::CwiseBinaryOp<
+ internal::scalar_sum_op<typename internal::traits<D>::Scalar>,
+ typename DenseBase<D>::ConstantReturnType,
+ const D>
operator+(const typename Eigen::MatrixBase<D> &m,
const typename Eigen::internal::traits<D>::Scalar &s) {
- return Eigen::CwiseUnaryOp<
- typename Eigen::internal::scalar_add_op<
- typename Eigen::internal::traits<D>::Scalar>,
- const D >(m.derived(),Eigen::internal::scalar_add_op<
- typename Eigen::internal::traits<D>::Scalar>(s));
+ return CwiseBinaryOp<
+ internal::scalar_sum_op<typename internal::traits<D>::Scalar>,
+ typename DenseBase<D>::ConstantReturnType,
+ const D>(DenseBase<D>::Constant(m.rows(), m.cols(), s), m.derived());
}
template<typename D>
inline const
-typename Eigen::CwiseUnaryOp<
- typename Eigen::internal::scalar_add_op<
- typename Eigen::internal::traits<D>::Scalar>,
- const D >
+typename Eigen::CwiseBinaryOp<
+ internal::scalar_sum_op<typename internal::traits<D>::Scalar>,
+ typename DenseBase<D>::ConstantReturnType,
+ const D>
operator+(const typename Eigen::internal::traits<D>::Scalar &s,
-const typename Eigen::MatrixBase<D> &m) {
- return Eigen::CwiseUnaryOp<
- typename Eigen::internal::scalar_add_op<
- typename Eigen::internal::traits<D>::Scalar>,
- const D >(m.derived(),Eigen::internal::scalar_add_op<
- typename Eigen::internal::traits<D>::Scalar>(s));
+ const typename Eigen::MatrixBase<D> &m) {
+ return CwiseBinaryOp<
+ internal::scalar_sum_op<typename internal::traits<D>::Scalar>,
+ typename DenseBase<D>::ConstantReturnType,
+ const D>(DenseBase<D>::Constant(m.rows(), m.cols(), s), m.derived());
}
-
-
template<typename D1,typename D2>
inline const
typename Eigen::CwiseBinaryOp<
@@ -82,14 +76,9 @@ abs( const Eigen::MatrixBase< D > &m ) {
return m.cwiseAbs();
}
-
-
} // end Eigen namespace
-
-
-
namespace boost {
namespace numeric {
namespace odeint {
diff --git a/boost/numeric/odeint/stepper/adaptive_adams_bashforth_moulton.hpp b/boost/numeric/odeint/stepper/adaptive_adams_bashforth_moulton.hpp
new file mode 100644
index 0000000000..0d3d0c1255
--- /dev/null
+++ b/boost/numeric/odeint/stepper/adaptive_adams_bashforth_moulton.hpp
@@ -0,0 +1,237 @@
+/*
+ boost/numeric/odeint/stepper/detail/adaptive_adams_bashforth_moulton.hpp
+
+ [begin_description]
+ Implemetation of an adaptive adams bashforth moulton stepper.
+ Used as the stepper for the controlled adams bashforth moulton stepper.
+ [end_description]
+
+ Copyright 2017 Valentin Noah Hartmann
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or
+ copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_NUMERIC_ODEINT_STEPPER_ADAPTIVE_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED
+#define BOOST_NUMERIC_ODEINT_STEPPER_ADAPTIVE_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED
+
+#include <boost/numeric/odeint/stepper/detail/adaptive_adams_coefficients.hpp>
+
+#include <boost/numeric/odeint/util/unwrap_reference.hpp>
+#include <boost/numeric/odeint/util/bind.hpp>
+#include <boost/numeric/odeint/util/copy.hpp>
+
+#include <boost/numeric/odeint/algebra/default_operations.hpp>
+#include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp>
+#include <boost/numeric/odeint/algebra/operations_dispatcher.hpp>
+
+#include <boost/numeric/odeint/util/state_wrapper.hpp>
+#include <boost/numeric/odeint/util/is_resizeable.hpp>
+#include <boost/numeric/odeint/util/resizer.hpp>
+
+#include <boost/numeric/odeint/stepper/stepper_categories.hpp>
+
+#include <boost/numeric/odeint/stepper/base/algebra_stepper_base.hpp>
+#include <boost/numeric/odeint/stepper/detail/rotating_buffer.hpp>
+
+namespace boost {
+namespace numeric {
+namespace odeint {
+
+template<
+size_t Steps,
+class State,
+class Value = double,
+class Deriv = State,
+class Time = Value,
+class Algebra = typename algebra_dispatcher< State >::algebra_type ,
+class Operations = typename operations_dispatcher< State >::operations_type,
+class Resizer = initially_resizer
+>
+class adaptive_adams_bashforth_moulton: public algebra_stepper_base< Algebra , Operations >
+{
+public:
+ static const size_t steps = Steps;
+
+ typedef unsigned short order_type;
+ static const order_type order_value = steps;
+
+ typedef State state_type;
+ typedef Value value_type;
+ typedef Deriv deriv_type;
+ typedef Time time_type;
+
+ typedef state_wrapper< state_type > wrapped_state_type;
+ typedef state_wrapper< deriv_type > wrapped_deriv_type;
+
+ typedef algebra_stepper_base< Algebra , Operations > algebra_stepper_base_type;
+ typedef typename algebra_stepper_base_type::algebra_type algebra_type;
+ typedef typename algebra_stepper_base_type::operations_type operations_type;
+ typedef Resizer resizer_type;
+ typedef error_stepper_tag stepper_category;
+
+ typedef detail::adaptive_adams_coefficients< Steps , Deriv , Value , Time , Algebra , Operations , Resizer > coeff_type;
+ typedef adaptive_adams_bashforth_moulton< Steps , State , Value , Deriv , Time , Algebra , Operations , Resizer > stepper_type;
+
+ order_type order() const { return order_value; };
+ order_type stepper_order() const { return order_value + 1; };
+ order_type error_order() const { return order_value; };
+
+ adaptive_adams_bashforth_moulton( const algebra_type &algebra = algebra_type() )
+ :algebra_stepper_base_type( algebra ), m_coeff(),
+ m_dxdt_resizer(), m_xnew_resizer(), m_xerr_resizer()
+ {};
+
+ template< class System >
+ void do_step(System system, state_type &inOut, time_type t, time_type dt )
+ {
+ m_xnew_resizer.adjust_size( inOut , detail::bind( &stepper_type::template resize_xnew_impl< state_type > , detail::ref( *this ) , detail::_1 ) );
+
+ do_step(system, inOut, t, m_xnew.m_v, dt, m_xerr.m_v);
+ boost::numeric::odeint::copy( m_xnew.m_v , inOut);
+ };
+
+ template< class System >
+ void do_step(System system, const state_type &in, time_type t, state_type &out, time_type dt )
+ {
+ do_step(system, in, t, out, dt, m_xerr.m_v);
+ };
+
+ template< class System >
+ void do_step(System system, state_type &inOut, time_type t, time_type dt, state_type &xerr)
+ {
+ m_xnew_resizer.adjust_size( inOut , detail::bind( &stepper_type::template resize_xnew_impl< state_type > , detail::ref( *this ) , detail::_1 ) );
+
+ do_step(system, inOut, t, m_xnew.m_v, dt, xerr);
+ boost::numeric::odeint::copy( m_xnew.m_v , inOut);
+ };
+
+ template< class System >
+ void do_step(System system, const state_type &in, time_type t, state_type &out, time_type dt , state_type &xerr)
+ {
+ do_step_impl(system, in, t, out, dt, xerr);
+
+ system(out, m_dxdt.m_v, t+dt);
+ m_coeff.do_step(m_dxdt.m_v);
+ m_coeff.confirm();
+
+ if(m_coeff.m_eo < order_value)
+ {
+ m_coeff.m_eo ++;
+ }
+ };
+
+ template< class ExplicitStepper, class System >
+ void initialize(ExplicitStepper stepper, System system, state_type &inOut, time_type &t, time_type dt)
+ {
+ reset();
+ dt = dt/static_cast< time_type >(order_value);
+
+ m_dxdt_resizer.adjust_size( inOut , detail::bind( &stepper_type::template resize_dxdt_impl< state_type > , detail::ref( *this ) , detail::_1 ) );
+
+ system( inOut , m_dxdt.m_v , t );
+ for( size_t i=0 ; i<order_value; ++i )
+ {
+ stepper.do_step_dxdt_impl( system, inOut, m_dxdt.m_v, t, dt );
+
+ system( inOut , m_dxdt.m_v , t + dt);
+
+ m_coeff.predict(t, dt);
+ m_coeff.do_step(m_dxdt.m_v);
+ m_coeff.confirm();
+
+ t += dt;
+
+ if(m_coeff.m_eo < order_value)
+ {
+ ++m_coeff.m_eo;
+ }
+ }
+ };
+
+ template< class System >
+ void initialize(System system, state_type &inOut, time_type &t, time_type dt)
+ {
+ reset();
+ dt = dt/static_cast< time_type >(order_value);
+
+ for(size_t i=0; i<order_value; ++i)
+ {
+ this->do_step(system, inOut, t, dt);
+ t += dt;
+ };
+ };
+
+ template< class System >
+ void do_step_impl(System system, const state_type & in, time_type t, state_type & out, time_type &dt, state_type &xerr)
+ {
+ size_t eO = m_coeff.m_eo;
+
+ m_xerr_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_xerr_impl< state_type > , detail::ref( *this ) , detail::_1 ) );
+ m_dxdt_resizer.adjust_size( in , detail::bind( &stepper_type::template resize_dxdt_impl< state_type > , detail::ref( *this ) , detail::_1 ) );
+
+ m_coeff.predict(t, dt);
+ if (m_coeff.m_steps_init == 1)
+ {
+ system(in, m_dxdt.m_v, t);
+ m_coeff.do_step(m_dxdt.m_v, 1);
+ }
+
+ boost::numeric::odeint::copy( in , out );
+ for(size_t i=0; i<eO; ++i)
+ {
+ this->m_algebra.for_each3(out, out, m_coeff.phi[1][i].m_v,
+ typename Operations::template scale_sum2<double, double>(1.0, dt*m_coeff.g[i]*m_coeff.beta[0][i]));
+ }
+
+ system(out, m_dxdt.m_v, t+dt);
+ m_coeff.do_step(m_dxdt.m_v);
+
+ this->m_algebra.for_each3(out, out, m_coeff.phi[0][eO].m_v,
+ typename Operations::template scale_sum2<double, double>(1.0, dt*m_coeff.g[eO]));
+
+ // error for current order
+ this->m_algebra.for_each2(xerr, m_coeff.phi[0][eO].m_v,
+ typename Operations::template scale_sum1<double>(dt*(m_coeff.g[eO])));
+ };
+
+ const coeff_type& coeff() const { return m_coeff; };
+ coeff_type & coeff() { return m_coeff; };
+
+ void reset() { m_coeff.reset(); };
+ const deriv_type & dxdt() const { return m_dxdt.m_v; };
+
+private:
+ template< class StateType >
+ bool resize_dxdt_impl( const StateType &x )
+ {
+ return adjust_size_by_resizeability( m_dxdt, x, typename is_resizeable<deriv_type>::type() );
+ };
+ template< class StateType >
+ bool resize_xnew_impl( const StateType &x )
+ {
+ return adjust_size_by_resizeability( m_xnew, x, typename is_resizeable<state_type>::type() );
+ };
+ template< class StateType >
+ bool resize_xerr_impl( const StateType &x )
+ {
+ return adjust_size_by_resizeability( m_xerr, x, typename is_resizeable<state_type>::type() );
+ };
+
+ coeff_type m_coeff;
+
+ resizer_type m_dxdt_resizer;
+ resizer_type m_xnew_resizer;
+ resizer_type m_xerr_resizer;
+
+ wrapped_deriv_type m_dxdt;
+ wrapped_state_type m_xnew;
+ wrapped_state_type m_xerr;
+};
+
+} // odeint
+} // numeric
+} // boost
+
+#endif \ No newline at end of file
diff --git a/boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp b/boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp
index 6a1eed15fb..22eb373bb8 100644
--- a/boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp
+++ b/boost/numeric/odeint/stepper/bulirsch_stoer_dense_out.hpp
@@ -391,6 +391,11 @@ public:
}
+protected:
+
+ time_type m_max_dt;
+
+
private:
template< class StateInOut , class StateVector >
@@ -667,8 +672,6 @@ private:
default_error_checker< value_type, algebra_type , operations_type > m_error_checker;
modified_midpoint_dense_out< state_type , value_type , deriv_type , time_type , algebra_type , operations_type , resizer_type > m_midpoint;
- time_type m_max_dt;
-
bool m_control_interpolation;
bool m_last_step_rejected;
diff --git a/boost/numeric/odeint/stepper/controlled_adams_bashforth_moulton.hpp b/boost/numeric/odeint/stepper/controlled_adams_bashforth_moulton.hpp
new file mode 100644
index 0000000000..85ee4d01c2
--- /dev/null
+++ b/boost/numeric/odeint/stepper/controlled_adams_bashforth_moulton.hpp
@@ -0,0 +1,322 @@
+/*
+ boost/numeric/odeint/stepper/detail/controlled_adams_bashforth_moulton.hpp
+
+ [begin_description]
+ Implemetation of an controlled adams bashforth moulton stepper.
+ [end_description]
+
+ Copyright 2017 Valentin Noah Hartmann
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or
+ copy at http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_NUMERIC_ODEINT_STEPPER_CONTROLLED_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED
+#define BOOST_NUMERIC_ODEINT_STEPPER_CONTROLLED_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED
+
+#include <boost/numeric/odeint/stepper/stepper_categories.hpp>
+#include <boost/numeric/odeint/stepper/controlled_step_result.hpp>
+
+#include <boost/numeric/odeint/stepper/adaptive_adams_bashforth_moulton.hpp>
+#include <boost/numeric/odeint/stepper/detail/pid_step_adjuster.hpp>
+
+#include <boost/numeric/odeint/util/unwrap_reference.hpp>
+#include <boost/numeric/odeint/util/is_resizeable.hpp>
+#include <boost/numeric/odeint/util/resizer.hpp>
+
+#include <boost/numeric/odeint/util/copy.hpp>
+#include <boost/numeric/odeint/util/bind.hpp>
+
+#include <iostream>
+
+namespace boost {
+namespace numeric {
+namespace odeint {
+
+template<
+size_t MaxOrder,
+class State,
+class Value = double,
+class Algebra = typename algebra_dispatcher< State >::algebra_type
+>
+class default_order_adjuster
+{
+public:
+ typedef State state_type;
+ typedef Value value_type;
+ typedef state_wrapper< state_type > wrapped_state_type;
+
+ typedef Algebra algebra_type;
+
+ default_order_adjuster( const algebra_type &algebra = algebra_type() )
+ : m_algebra( algebra )
+ {};
+
+ size_t adjust_order(size_t order, size_t init, boost::array<wrapped_state_type, 4> &xerr)
+ {
+ using std::abs;
+
+ value_type errc = abs(m_algebra.norm_inf(xerr[2].m_v));
+
+ value_type errm1 = 3*errc;
+ value_type errm2 = 3*errc;
+
+ if(order > 2)
+ {
+ errm2 = abs(m_algebra.norm_inf(xerr[0].m_v));
+ }
+ if(order >= 2)
+ {
+ errm1 = abs(m_algebra.norm_inf(xerr[1].m_v));
+ }
+
+ size_t o_new = order;
+
+ if(order == 2 && errm1 <= 0.5*errc)
+ {
+ o_new = order - 1;
+ }
+ else if(order > 2 && errm2 < errc && errm1 < errc)
+ {
+ o_new = order - 1;
+ }
+
+ if(init < order)
+ {
+ return order+1;
+ }
+ else if(o_new == order - 1)
+ {
+ return order-1;
+ }
+ else if(order <= MaxOrder)
+ {
+ value_type errp = abs(m_algebra.norm_inf(xerr[3].m_v));
+
+ if(order > 1 && errm1 < errc && errp)
+ {
+ return order-1;
+ }
+ else if(order < MaxOrder && errp < (0.5-0.25*order/MaxOrder) * errc)
+ {
+ return order+1;
+ }
+ }
+
+ return order;
+ };
+private:
+ algebra_type m_algebra;
+};
+
+template<
+class ErrorStepper,
+class StepAdjuster = detail::pid_step_adjuster< typename ErrorStepper::state_type,
+ typename ErrorStepper::value_type,
+ typename ErrorStepper::deriv_type,
+ typename ErrorStepper::time_type,
+ typename ErrorStepper::algebra_type,
+ typename ErrorStepper::operations_type,
+ detail::H211PI
+ >,
+class OrderAdjuster = default_order_adjuster< ErrorStepper::order_value,
+ typename ErrorStepper::state_type,
+ typename ErrorStepper::value_type,
+ typename ErrorStepper::algebra_type
+ >,
+class Resizer = initially_resizer
+>
+class controlled_adams_bashforth_moulton
+{
+public:
+ typedef ErrorStepper stepper_type;
+
+ static const typename stepper_type::order_type order_value = stepper_type::order_value;
+
+ typedef typename stepper_type::state_type state_type;
+ typedef typename stepper_type::value_type value_type;
+ typedef typename stepper_type::deriv_type deriv_type;
+ typedef typename stepper_type::time_type time_type;
+
+ typedef typename stepper_type::algebra_type algebra_type;
+ typedef typename stepper_type::operations_type operations_type;
+ typedef Resizer resizer_type;
+
+ typedef StepAdjuster step_adjuster_type;
+ typedef OrderAdjuster order_adjuster_type;
+ typedef controlled_stepper_tag stepper_category;
+
+ typedef typename stepper_type::wrapped_state_type wrapped_state_type;
+ typedef typename stepper_type::wrapped_deriv_type wrapped_deriv_type;
+ typedef boost::array< wrapped_state_type , 4 > error_storage_type;
+
+ typedef typename stepper_type::coeff_type coeff_type;
+ typedef controlled_adams_bashforth_moulton< ErrorStepper , StepAdjuster , OrderAdjuster , Resizer > controlled_stepper_type;
+
+ controlled_adams_bashforth_moulton(step_adjuster_type step_adjuster = step_adjuster_type())
+ :m_stepper(),
+ m_dxdt_resizer(), m_xerr_resizer(), m_xnew_resizer(),
+ m_step_adjuster( step_adjuster ), m_order_adjuster()
+ {};
+
+ template< class ExplicitStepper, class System >
+ void initialize(ExplicitStepper stepper, System system, state_type &inOut, time_type &t, time_type dt)
+ {
+ m_stepper.initialize(stepper, system, inOut, t, dt);
+ };
+
+ template< class System >
+ void initialize(System system, state_type &inOut, time_type &t, time_type dt)
+ {
+ m_stepper.initialize(system, inOut, t, dt);
+ };
+
+ template< class ExplicitStepper, class System >
+ void initialize_controlled(ExplicitStepper stepper, System system, state_type &inOut, time_type &t, time_type &dt)
+ {
+ reset();
+ coeff_type &coeff = m_stepper.coeff();
+
+ m_dxdt_resizer.adjust_size( inOut , detail::bind( &controlled_stepper_type::template resize_dxdt_impl< state_type > , detail::ref( *this ) , detail::_1 ) );
+
+ controlled_step_result res = fail;
+
+ for( size_t i=0 ; i<order_value; ++i )
+ {
+ do
+ {
+ res = stepper.try_step( system, inOut, t, dt );
+ }
+ while(res != success);
+
+ system( inOut , m_dxdt.m_v , t );
+
+ coeff.predict(t-dt, dt);
+ coeff.do_step(m_dxdt.m_v);
+ coeff.confirm();
+
+ if(coeff.m_eo < order_value)
+ {
+ ++coeff.m_eo;
+ }
+ }
+ }
+
+ template< class System >
+ controlled_step_result try_step(System system, state_type & inOut, time_type &t, time_type &dt)
+ {
+ m_xnew_resizer.adjust_size( inOut , detail::bind( &controlled_stepper_type::template resize_xnew_impl< state_type > , detail::ref( *this ) , detail::_1 ) );
+
+ controlled_step_result res = try_step(system, inOut, t, m_xnew.m_v, dt);
+
+ if(res == success)
+ {
+ boost::numeric::odeint::copy( m_xnew.m_v , inOut);
+ }
+
+ return res;
+ };
+
+ template< class System >
+ controlled_step_result try_step(System system, const state_type & in, time_type &t, state_type & out, time_type &dt)
+ {
+ m_xerr_resizer.adjust_size( in , detail::bind( &controlled_stepper_type::template resize_xerr_impl< state_type > , detail::ref( *this ) , detail::_1 ) );
+ m_dxdt_resizer.adjust_size( in , detail::bind( &controlled_stepper_type::template resize_dxdt_impl< state_type > , detail::ref( *this ) , detail::_1 ) );
+
+ m_stepper.do_step_impl(system, in, t, out, dt, m_xerr[2].m_v);
+
+ coeff_type &coeff = m_stepper.coeff();
+
+ time_type dtPrev = dt;
+ dt = m_step_adjuster.adjust_stepsize(coeff.m_eo, dt, m_xerr[2].m_v, out, m_stepper.dxdt() );
+
+ if(dt / dtPrev >= step_adjuster_type::threshold())
+ {
+ system(out, m_dxdt.m_v, t+dtPrev);
+
+ coeff.do_step(m_dxdt.m_v);
+ coeff.confirm();
+
+ t += dtPrev;
+
+ size_t eo = coeff.m_eo;
+
+ // estimate errors for next step
+ double factor = 1;
+ algebra_type m_algebra;
+
+ m_algebra.for_each2(m_xerr[2].m_v, coeff.phi[1][eo].m_v,
+ typename operations_type::template scale_sum1<double>(factor*dt*(coeff.gs[eo])));
+
+ if(eo > 1)
+ {
+ m_algebra.for_each2(m_xerr[1].m_v, coeff.phi[1][eo-1].m_v,
+ typename operations_type::template scale_sum1<double>(factor*dt*(coeff.gs[eo-1])));
+ }
+ if(eo > 2)
+ {
+ m_algebra.for_each2(m_xerr[0].m_v, coeff.phi[1][eo-2].m_v,
+ typename operations_type::template scale_sum1<double>(factor*dt*(coeff.gs[eo-2])));
+ }
+ if(eo < order_value && coeff.m_eo < coeff.m_steps_init-1)
+ {
+ m_algebra.for_each2(m_xerr[3].m_v, coeff.phi[1][eo+1].m_v,
+ typename operations_type::template scale_sum1<double>(factor*dt*(coeff.gs[eo+1])));
+ }
+
+ // adjust order
+ coeff.m_eo = m_order_adjuster.adjust_order(coeff.m_eo, coeff.m_steps_init-1, m_xerr);
+
+ return success;
+ }
+ else
+ {
+ return fail;
+ }
+ };
+
+ void reset() { m_stepper.reset(); };
+
+private:
+ template< class StateType >
+ bool resize_dxdt_impl( const StateType &x )
+ {
+ return adjust_size_by_resizeability( m_dxdt, x, typename is_resizeable<deriv_type>::type() );
+ };
+ template< class StateType >
+ bool resize_xerr_impl( const StateType &x )
+ {
+ bool resized( false );
+
+ for(size_t i=0; i<m_xerr.size(); ++i)
+ {
+ resized |= adjust_size_by_resizeability( m_xerr[i], x, typename is_resizeable<state_type>::type() );
+ }
+ return resized;
+ };
+ template< class StateType >
+ bool resize_xnew_impl( const StateType &x )
+ {
+ return adjust_size_by_resizeability( m_xnew, x, typename is_resizeable<state_type>::type() );
+ };
+
+ stepper_type m_stepper;
+
+ wrapped_deriv_type m_dxdt;
+ error_storage_type m_xerr;
+ wrapped_state_type m_xnew;
+
+ resizer_type m_dxdt_resizer;
+ resizer_type m_xerr_resizer;
+ resizer_type m_xnew_resizer;
+
+ step_adjuster_type m_step_adjuster;
+ order_adjuster_type m_order_adjuster;
+};
+
+} // odeint
+} // numeric
+} // boost
+
+#endif \ No newline at end of file
diff --git a/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp b/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp
index aac2b02dca..be00827f61 100644
--- a/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp
+++ b/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp
@@ -163,7 +163,7 @@ public:
time_type get_max_dt() { return m_max_dt; }
-private:
+protected:
time_type m_max_dt;
};
@@ -411,10 +411,11 @@ public:
template< class System , class StateIn , class DerivIn , class StateOut >
controlled_step_result try_step( System system , const StateIn &in , const DerivIn &dxdt , time_type &t , StateOut &out , time_type &dt )
{
- if( !m_step_adjuster.check_step_size_limit(dt) )
+ unwrapped_step_adjuster &step_adjuster = m_step_adjuster;
+ if( !step_adjuster.check_step_size_limit(dt) )
{
// given dt was above step size limit - adjust and return fail;
- dt = m_step_adjuster.get_max_dt();
+ dt = step_adjuster.get_max_dt();
return fail;
}
@@ -428,13 +429,13 @@ public:
if( max_rel_err > 1.0 )
{
// error too big, decrease step size and reject this step
- dt = m_step_adjuster.decrease_step(dt, max_rel_err, m_stepper.error_order());
+ dt = step_adjuster.decrease_step(dt, max_rel_err, m_stepper.error_order());
return fail;
} else
{
// otherwise, increase step size and accept
t += dt;
- dt = m_step_adjuster.increase_step(dt, max_rel_err, m_stepper.stepper_order());
+ dt = step_adjuster.increase_step(dt, max_rel_err, m_stepper.stepper_order());
return success;
}
}
@@ -505,6 +506,7 @@ private:
stepper_type m_stepper;
error_checker_type m_error_checker;
step_adjuster_type m_step_adjuster;
+ typedef typename unwrap_reference< step_adjuster_type >::type unwrapped_step_adjuster;
resizer_type m_dxdt_resizer;
resizer_type m_xerr_resizer;
@@ -584,7 +586,7 @@ public:
const step_adjuster_type &step_adjuster = step_adjuster_type() ,
const stepper_type &stepper = stepper_type()
)
- : m_stepper( stepper ) , m_error_checker( error_checker ) , m_step_adjuster(step_adjuster) ,
+ : m_stepper( stepper ) , m_error_checker( error_checker ) , m_step_adjuster(step_adjuster) ,
m_first_call( true )
{ }
@@ -751,10 +753,11 @@ public:
controlled_step_result try_step( System system , const StateIn &in , const DerivIn &dxdt_in , time_type &t ,
StateOut &out , DerivOut &dxdt_out , time_type &dt )
{
- if( !m_step_adjuster.check_step_size_limit(dt) )
+ unwrapped_step_adjuster &step_adjuster = m_step_adjuster;
+ if( !step_adjuster.check_step_size_limit(dt) )
{
// given dt was above step size limit - adjust and return fail;
- dt = m_step_adjuster.get_max_dt();
+ dt = step_adjuster.get_max_dt();
return fail;
}
@@ -770,12 +773,12 @@ public:
if( max_rel_err > 1.0 )
{
// error too big, decrease step size and reject this step
- dt = m_step_adjuster.decrease_step(dt, max_rel_err, m_stepper.error_order());
+ dt = step_adjuster.decrease_step(dt, max_rel_err, m_stepper.error_order());
return fail;
}
// otherwise, increase step size and accept
t += dt;
- dt = m_step_adjuster.increase_step(dt, max_rel_err, m_stepper.stepper_order());
+ dt = step_adjuster.increase_step(dt, max_rel_err, m_stepper.stepper_order());
return success;
}
@@ -903,6 +906,7 @@ private:
stepper_type m_stepper;
error_checker_type m_error_checker;
step_adjuster_type m_step_adjuster;
+ typedef typename unwrap_reference< step_adjuster_type >::type unwrapped_step_adjuster;
resizer_type m_dxdt_resizer;
resizer_type m_xerr_resizer;
diff --git a/boost/numeric/odeint/stepper/dense_output_runge_kutta.hpp b/boost/numeric/odeint/stepper/dense_output_runge_kutta.hpp
index 94abc5af99..83982dc7bc 100644
--- a/boost/numeric/odeint/stepper/dense_output_runge_kutta.hpp
+++ b/boost/numeric/odeint/stepper/dense_output_runge_kutta.hpp
@@ -126,7 +126,7 @@ public:
m_t_old = m_t;
m_t += m_dt;
toggle_current_state();
- return std::make_pair( m_t_old , m_dt );
+ return std::make_pair( m_t_old , m_t );
}
/*
diff --git a/boost/numeric/odeint/stepper/detail/adaptive_adams_coefficients.hpp b/boost/numeric/odeint/stepper/detail/adaptive_adams_coefficients.hpp
new file mode 100644
index 0000000000..c1029a167b
--- /dev/null
+++ b/boost/numeric/odeint/stepper/detail/adaptive_adams_coefficients.hpp
@@ -0,0 +1,207 @@
+/*
+ boost/numeric/odeint/stepper/detail/adaptive_adams_coefficients.hpp
+
+ [begin_description]
+ Calculation of the coefficients for the adaptive adams stepper.
+ [end_description]
+
+ Copyright 2017 Valentin Noah Hartmann
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or
+ copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAPTIVE_ADAMS_COEFFICIENTS_HPP_INCLUDED
+#define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAPTIVE_ADAMS_COEFFICIENTS_HPP_INCLUDED
+
+#include <boost/numeric/odeint/stepper/detail/rotating_buffer.hpp>
+
+#include <boost/numeric/odeint/util/state_wrapper.hpp>
+#include <boost/numeric/odeint/util/is_resizeable.hpp>
+#include <boost/numeric/odeint/util/resizer.hpp>
+
+#include <boost/numeric/odeint/util/unwrap_reference.hpp>
+#include <boost/numeric/odeint/util/bind.hpp>
+
+#include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp>
+#include <boost/numeric/odeint/algebra/operations_dispatcher.hpp>
+
+#include <boost/array.hpp>
+
+namespace boost {
+namespace numeric {
+namespace odeint {
+namespace detail {
+
+template<
+size_t Steps,
+class Deriv,
+class Value = double,
+class Time = double,
+class Algebra = typename algebra_dispatcher< Deriv >::algebra_type,
+class Operations = typename operations_dispatcher< Deriv >::operations_type,
+class Resizer = initially_resizer
+>
+class adaptive_adams_coefficients
+{
+public:
+ static const size_t steps = Steps;
+
+ typedef unsigned short order_type;
+ static const order_type order_value = steps;
+
+ typedef Value value_type;
+ typedef Deriv deriv_type;
+ typedef Time time_type;
+
+ typedef state_wrapper< deriv_type > wrapped_deriv_type;
+ typedef rotating_buffer< time_type , steps+1 > time_storage_type;
+
+ typedef Algebra algebra_type;
+ typedef Operations operations_type;
+ typedef Resizer resizer_type;
+
+ typedef adaptive_adams_coefficients< Steps , Deriv , Value , Time , Algebra , Operations , Resizer > aac_type;
+
+ adaptive_adams_coefficients( const algebra_type &algebra = algebra_type())
+ :m_eo(1), m_steps_init(1), beta(), phi(), m_ns(0), m_time_storage(),
+ m_algebra(algebra),
+ m_phi_resizer()
+ {
+ for (size_t i=0; i<order_value+2; ++i)
+ {
+ c[i] = 1.0/(i+1);
+ c[c_size+i] = 1.0/((i+1)*(i+2));
+ }
+
+ g[0] = c[0];
+ g[1] = c[c_size];
+
+ beta[0][0] = 1;
+ beta[1][0] = 1;
+
+ gs[0] = 1.0;
+ gs[1] = -1.0/2;
+ gs[2] = -1.0/12;
+ gs[3] = -1.0/24;
+ gs[4] = -19.0/720;
+ gs[5] = -3.0/160;
+ gs[6] = -863.0/60480;
+ gs[7] = -275.0/24192;
+ gs[8] = -33953.0/3628800;
+ gs[9] = 35.0/4436;
+ gs[10] = 40.0/5891;
+ gs[11] = 37.0/6250;
+ gs[12] = 25.0/4771;
+ gs[13] = 40.0/8547;
+ };
+
+ void predict(time_type t, time_type dt)
+ {
+ using std::abs;
+
+ m_time_storage[0] = t;
+
+ if (abs(m_time_storage[0] - m_time_storage[1] - dt) > 1e-16 || m_eo >= m_ns)
+ {
+ m_ns = 0;
+ }
+ else if (m_ns < order_value + 2)
+ {
+ m_ns++;
+ }
+
+ for(size_t i=1+m_ns; i<m_eo+1 && i<m_steps_init; ++i)
+ {
+ time_type diff = m_time_storage[0] - m_time_storage[i];
+ beta[0][i] = beta[0][i-1]*(m_time_storage[0] + dt - m_time_storage[i-1])/diff;
+ }
+
+ for(size_t i=2+m_ns; i<m_eo+2 && i<m_steps_init+1; ++i)
+ {
+ time_type diff = m_time_storage[0] + dt - m_time_storage[i-1];
+ for(size_t j=0; j<m_eo+1-i+1; ++j)
+ {
+ c[c_size*i+j] = c[c_size*(i-1)+j] - c[c_size*(i-1)+j+1]*dt/diff;
+ }
+
+ g[i] = c[c_size*i];
+ }
+ };
+
+ void do_step(const deriv_type &dxdt, const int o = 0)
+ {
+ m_phi_resizer.adjust_size( dxdt , detail::bind( &aac_type::template resize_phi_impl< deriv_type > , detail::ref( *this ) , detail::_1 ) );
+
+ phi[o][0].m_v = dxdt;
+
+ for(size_t i=1; i<m_eo+3 && i<m_steps_init+2 && i<order_value+2; ++i)
+ {
+ if (o == 0)
+ {
+ this->m_algebra.for_each3(phi[o][i].m_v, phi[o][i-1].m_v, phi[o+1][i-1].m_v,
+ typename Operations::template scale_sum2<value_type, value_type>(1.0, -beta[o][i-1]));
+ }
+ else
+ {
+ this->m_algebra.for_each2(phi[o][i].m_v, phi[o][i-1].m_v,
+ typename Operations::template scale_sum1<value_type>(1.0));
+ }
+ }
+ };
+
+ void confirm()
+ {
+ beta.rotate();
+ phi.rotate();
+ m_time_storage.rotate();
+
+ if(m_steps_init < order_value+1)
+ {
+ ++m_steps_init;
+ }
+ };
+
+ void reset() { m_eo = 1; m_steps_init = 1; };
+
+ size_t m_eo;
+ size_t m_steps_init;
+
+ rotating_buffer<boost::array<value_type, order_value+1>, 2> beta; // beta[0] = beta(n)
+ rotating_buffer<boost::array<wrapped_deriv_type, order_value+2>, 3> phi; // phi[0] = phi(n+1)
+ boost::array<value_type, order_value + 2> g;
+ boost::array<value_type, 14> gs;
+
+private:
+ template< class StateType >
+ bool resize_phi_impl( const StateType &x )
+ {
+ bool resized( false );
+
+ for(size_t i=0; i<(order_value + 2); ++i)
+ {
+ resized |= adjust_size_by_resizeability( phi[0][i], x, typename is_resizeable<deriv_type>::type() );
+ resized |= adjust_size_by_resizeability( phi[1][i], x, typename is_resizeable<deriv_type>::type() );
+ resized |= adjust_size_by_resizeability( phi[2][i], x, typename is_resizeable<deriv_type>::type() );
+ }
+ return resized;
+ };
+
+ size_t m_ns;
+
+ time_storage_type m_time_storage;
+ static const size_t c_size = order_value + 2;
+ boost::array<value_type, c_size*c_size> c;
+
+ algebra_type m_algebra;
+
+ resizer_type m_phi_resizer;
+};
+
+} // detail
+} // odeint
+} // numeric
+} // boost
+
+#endif \ No newline at end of file
diff --git a/boost/numeric/odeint/stepper/detail/pid_step_adjuster.hpp b/boost/numeric/odeint/stepper/detail/pid_step_adjuster.hpp
new file mode 100644
index 0000000000..7c0f258b50
--- /dev/null
+++ b/boost/numeric/odeint/stepper/detail/pid_step_adjuster.hpp
@@ -0,0 +1,199 @@
+/*
+ boost/numeric/odeint/stepper/detail/pid_step_adjuster.hpp
+
+ [begin_description]
+ Implementation of the stepsize controller for the controlled adams bashforth moulton stepper.
+ [end_description]
+
+ Copyright 2017 Valentin Noah Hartmann
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or
+ copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_PID_STEP_ADJUSTER_HPP_INCLUDED
+#define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_PID_STEP_ADJUSTER_HPP_INCLUDED
+
+#include <boost/numeric/odeint/stepper/detail/rotating_buffer.hpp>
+#include <boost/numeric/odeint/stepper/detail/pid_step_adjuster_coefficients.hpp>
+
+#include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp>
+#include <boost/numeric/odeint/algebra/operations_dispatcher.hpp>
+
+#include <math.h>
+
+namespace boost {
+namespace numeric {
+namespace odeint {
+namespace detail {
+
+template<
+class Value = double,
+class Time = double
+>
+struct pid_op
+{
+public:
+ typedef Value value_type;
+ typedef Time time_type;
+
+ const double beta1;
+ const double beta2;
+ const double beta3;
+ const double alpha1;
+ const double alpha2;
+
+ const time_type dt1;
+ const time_type dt2;
+ const time_type dt3;
+
+ const size_t m_steps;
+
+ pid_op(const size_t steps, const double _dt1, const double _dt2, const double _dt3,
+ const double b1 = 1, const double b2 = 0, const double b3 = 0, const double a1 = 0, const double a2 = 0)
+ :beta1(b1), beta2(b2), beta3(b3), alpha1(a1), alpha2(a2),
+ dt1(_dt1), dt2(_dt2), dt3(_dt3),
+ m_steps(steps)
+ {};
+
+ template<class T1, class T2, class T3, class T4>
+ void operator()(T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4)
+ {
+ using std::abs;
+
+ t1 = adapted_pow(abs(t2), -beta1/(m_steps + 1)) *
+ adapted_pow(abs(t3), -beta2/(m_steps + 1)) *
+ adapted_pow(abs(t4), -beta3/(m_steps + 1)) *
+ adapted_pow(abs(dt1/dt2), -alpha1/(m_steps + 1))*
+ adapted_pow(abs(dt2/dt3), -alpha2/(m_steps + 1));
+
+ t1 = 1/t1;
+ };
+
+ template<class T1, class T2>
+ void operator()(T1 &t1, const T2 &t2)
+ {
+ using std::abs;
+
+ t1 = adapted_pow(abs(t2), -beta1/(m_steps + 1));
+
+ t1 = 1/t1;
+ };
+
+private:
+ template<class T>
+ inline value_type adapted_pow(T base, double exp)
+ {
+ if(exp == 0)
+ {
+ return 1;
+ }
+ else if (exp > 0)
+ {
+ return pow(base, exp);
+ }
+ else
+ {
+ return 1/pow(base, -exp);
+ }
+ };
+};
+
+template<
+class State,
+class Value = double,
+class Deriv = State,
+class Time = double,
+class Algebra = typename algebra_dispatcher< State >::algebra_type,
+class Operations = typename operations_dispatcher< Deriv >::operations_type,
+size_t Type = BASIC
+>
+struct pid_step_adjuster
+{
+public:
+ static double threshold() { return 0.9; };
+
+ typedef State state_type;
+ typedef Value value_type;
+ typedef Deriv deriv_type;
+ typedef Time time_type;
+
+ typedef Algebra algebra_type;
+ typedef Operations operations_type;
+
+ typedef rotating_buffer<state_type, 3> error_storage_type;
+ typedef rotating_buffer<time_type, 3> time_storage_type;
+ typedef pid_step_adjuster_coefficients<Type> coeff_type;
+
+ pid_step_adjuster(double abs_tol = 1e-6, double rel_tol = 1e-6, time_type dtmax = 1.0)
+ :m_dtmax(dtmax), m_error_storage(), m_dt_storage(), m_init(0),
+ m_abs_tol(abs_tol), m_rel_tol(rel_tol)
+ {};
+
+ time_type adjust_stepsize(const size_t steps, time_type dt, state_type &err, const state_type &x, const deriv_type &dxdt)
+ {
+ using std::abs;
+ m_algebra.for_each3( err , x , dxdt ,
+ typename operations_type::template rel_error< value_type >( m_abs_tol , m_rel_tol , 1.0 , 1.0 * abs(get_unit_value( dt )) ) );
+
+ m_error_storage[0] = err;
+ m_dt_storage[0] = dt;
+
+ if(m_init >= 2)
+ {
+ m_algebra.for_each4(err, m_error_storage[0], m_error_storage[1], m_error_storage[2],
+ pid_op<>(steps, m_dt_storage[0], m_dt_storage[1], m_dt_storage[2],
+ m_coeff[0], m_coeff[1], m_coeff[2], m_coeff[3], m_coeff[4]));
+ }
+ else
+ {
+ m_algebra.for_each2(err, m_error_storage[0],
+ pid_op<>(steps, m_dt_storage[0], m_dt_storage[1], m_dt_storage[2], 0.7));
+ }
+
+ value_type ratio = 1 / m_algebra.norm_inf(err);
+
+ value_type kappa = 1.0;
+ ratio = 1.0 + kappa*atan((ratio - 1) / kappa);
+
+ if(ratio*dt >= m_dtmax)
+ {
+ ratio = m_dtmax / dt;
+ }
+
+ if(ratio >= threshold())
+ {
+ m_error_storage.rotate();
+ m_dt_storage.rotate();
+
+ ++m_init;
+ }
+ else
+ {
+ m_init = 0;
+ }
+
+ return dt * static_cast<time_type>(ratio);
+ };
+
+private:
+ algebra_type m_algebra;
+
+ time_type m_dtmax;
+ error_storage_type m_error_storage;
+ time_storage_type m_dt_storage;
+
+ size_t m_init;
+ double m_abs_tol;
+ double m_rel_tol;
+
+ coeff_type m_coeff;
+};
+
+} // detail
+} // odeint
+} // numeric
+} // boost
+
+#endif \ No newline at end of file
diff --git a/boost/numeric/odeint/stepper/detail/pid_step_adjuster_coefficients.hpp b/boost/numeric/odeint/stepper/detail/pid_step_adjuster_coefficients.hpp
new file mode 100644
index 0000000000..2dee6ed192
--- /dev/null
+++ b/boost/numeric/odeint/stepper/detail/pid_step_adjuster_coefficients.hpp
@@ -0,0 +1,180 @@
+/*
+ boost/numeric/odeint/stepper/detail/pid_step_adjuster_coefficients.hpp
+
+ [begin_description]
+ Coefficients for the PID stepsize controller.
+ [end_description]
+
+ Copyright 2017 Valentin Noah Hartmann
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or
+ copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_PID_STEP_ADJUSTER_COEFFICIENTS_HPP_INCLUDED
+#define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_PID_STEP_ADJUSTER_COEFFICIENTS_HPP_INCLUDED
+
+#include <boost/array.hpp>
+
+namespace boost {
+namespace numeric {
+namespace odeint {
+namespace detail {
+
+enum adjuster_type{
+ BASIC,
+ H0211,
+ H211b,
+ H211PI,
+ H0312,
+ H312b,
+ H312PID,
+ H0321,
+ H321
+};
+
+template<int Type>
+class pid_step_adjuster_coefficients;
+
+template<>
+class pid_step_adjuster_coefficients<BASIC> : public boost::array<double, 5>
+{
+public:
+ pid_step_adjuster_coefficients()
+ : boost::array<double, 5>()
+ {
+ (*this)[0] = 1.0;
+ (*this)[1] = 0.0;
+ (*this)[2] = 0.0;
+ (*this)[3] = 0.0;
+ (*this)[4] = 0.0;
+ }
+};
+
+template<>
+class pid_step_adjuster_coefficients<H0211> : public boost::array<double, 5>
+{
+public:
+ pid_step_adjuster_coefficients()
+ : boost::array<double, 5>()
+ {
+ (*this)[0] = 1.0 / 2.0;
+ (*this)[1] = 1.0 / 2.0;
+ (*this)[2] = 0.0;
+ (*this)[3] = 1.0 / 2.0;
+ (*this)[4] = 0.0;
+ }
+};
+
+template<>
+class pid_step_adjuster_coefficients<H211b> : public boost::array<double, 5>
+{
+public:
+ pid_step_adjuster_coefficients()
+ : boost::array<double, 5>()
+ {
+ (*this)[0] = 1.0 / 5.0;
+ (*this)[1] = 2.0 / 5.0;
+ (*this)[2] = 0.0;
+ (*this)[3] = 1.0 / 5.0;
+ (*this)[4] = 0.0;
+ }
+};
+
+template<>
+class pid_step_adjuster_coefficients<H211PI> : public boost::array<double, 5>
+{
+public:
+ pid_step_adjuster_coefficients()
+ : boost::array<double, 5>()
+ {
+ (*this)[0] = 1.0 / 6.0;
+ (*this)[1] = 2.0 / 6.0;
+ (*this)[2] = 0.0;
+ (*this)[3] = 0.0;
+ (*this)[4] = 0.0;
+ }
+};
+
+template<>
+class pid_step_adjuster_coefficients<H0312> : public boost::array<double, 5>
+{
+public:
+ pid_step_adjuster_coefficients()
+ : boost::array<double, 5>()
+ {
+ (*this)[0] = 1.0 / 4.0;
+ (*this)[1] = 2.0 / 2.0;
+ (*this)[2] = 1.0 / 4.0;
+ (*this)[3] = 3.0 / 4.0;
+ (*this)[4] = 1.0 / 4.0;
+ }
+};
+
+template<>
+class pid_step_adjuster_coefficients<H312b> : public boost::array<double, 5>
+{
+public:
+ pid_step_adjuster_coefficients()
+ : boost::array<double, 5>()
+ {
+ (*this)[0] = 1.0 / 6.0;
+ (*this)[1] = 2.0 / 6.0;
+ (*this)[2] = 1.0 / 6.0;
+ (*this)[3] = 3.0 / 6.0;
+ (*this)[4] = 1.0 / 6.0;
+ }
+};
+
+template<>
+class pid_step_adjuster_coefficients<H312PID> : public boost::array<double, 5>
+{
+public:
+ pid_step_adjuster_coefficients()
+ : boost::array<double, 5>()
+ {
+ (*this)[0] = 1.0 / 18.0;
+ (*this)[1] = 2.0 / 9.0;
+ (*this)[2] = 1.0 / 18.0;
+ (*this)[3] = 0.0;
+ (*this)[4] = 0.0;
+ }
+};
+
+template<>
+class pid_step_adjuster_coefficients<H0321> : public boost::array<double, 5>
+{
+public:
+ pid_step_adjuster_coefficients()
+ : boost::array<double, 5>()
+ {
+ (*this)[0] = 5.0 / 4.0;
+ (*this)[1] = 1.0 / 2.0;
+ (*this)[2] = -3.0 / 4.0;
+ (*this)[3] = -1.0 / 4.0;
+ (*this)[4] = -3.0 / 4.0;
+ }
+};
+
+template<>
+class pid_step_adjuster_coefficients<H321> : public boost::array<double, 5>
+{
+public:
+ pid_step_adjuster_coefficients()
+ : boost::array<double, 5>()
+ {
+ (*this)[0] = 1.0 / 3.0;
+ (*this)[1] = 1.0 / 18.0;
+ (*this)[2] = -5.0 / 18.0;
+ (*this)[3] = -5.0 / 16.0;
+ (*this)[4] = -1.0 / 6.0;
+ }
+};
+
+} // detail
+} // odeint
+} // numeric
+} // boost
+
+#endif \ No newline at end of file
diff --git a/boost/numeric/odeint/stepper/generation.hpp b/boost/numeric/odeint/stepper/generation.hpp
index 90ad2b9a76..a051d13bfa 100644
--- a/boost/numeric/odeint/stepper/generation.hpp
+++ b/boost/numeric/odeint/stepper/generation.hpp
@@ -29,6 +29,7 @@
#include <boost/numeric/odeint/stepper/generation/generation_runge_kutta_dopri5.hpp>
#include <boost/numeric/odeint/stepper/generation/generation_runge_kutta_fehlberg78.hpp>
+#include <boost/numeric/odeint/stepper/generation/generation_controlled_adams_bashforth_moulton.hpp>
#include <boost/numeric/odeint/stepper/generation/generation_rosenbrock4.hpp>
diff --git a/boost/numeric/odeint/stepper/generation/generation_controlled_adams_bashforth_moulton.hpp b/boost/numeric/odeint/stepper/generation/generation_controlled_adams_bashforth_moulton.hpp
new file mode 100644
index 0000000000..ca95a1f557
--- /dev/null
+++ b/boost/numeric/odeint/stepper/generation/generation_controlled_adams_bashforth_moulton.hpp
@@ -0,0 +1,59 @@
+/*
+ boost/numeric/odeint/stepper/detail/generation_controlled_adams_bashforth_moulton.hpp
+
+ [begin_description]
+ Spezialization of the generation functions for creation of the controlled adams bashforth moulton stepper.
+ [end_description]
+
+ Copyright 2017 Valentin Noah Hartmann
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or
+ copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef GENERATION_CONTROLLED_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED
+#define GENERATION_CONTROLLED_ADAMS_BASHFORTH_MOULTON_HPP_INCLUDED
+
+#include <boost/numeric/odeint/stepper/adaptive_adams_bashforth_moulton.hpp>
+#include <boost/numeric/odeint/stepper/controlled_adams_bashforth_moulton.hpp>
+#include <boost/numeric/odeint/stepper/generation/make_controlled.hpp>
+
+namespace boost {
+namespace numeric {
+namespace odeint {
+
+template< size_t Steps, class State , class Value , class Deriv , class Time , class Algebra , class Operations , class Resizer >
+struct get_controller< adaptive_adams_bashforth_moulton< Steps, State , Value , Deriv , Time , Algebra , Operations , Resizer > >
+{
+ typedef adaptive_adams_bashforth_moulton<Steps, State, Value, Deriv, Time, Algebra, Operations, Resizer> stepper_type;
+ typedef controlled_adams_bashforth_moulton< stepper_type > type;
+};
+
+// controller factory for controlled_adams_bashforth_moulton
+template< class Stepper >
+struct controller_factory< Stepper , controlled_adams_bashforth_moulton< Stepper > >
+{
+ typedef Stepper stepper_type;
+ typedef controlled_adams_bashforth_moulton< stepper_type > controller_type;
+ typedef typename controller_type::step_adjuster_type step_adjuster_type;
+ typedef typename stepper_type::value_type value_type;
+ typedef typename stepper_type::value_type time_type;
+
+ controller_type operator()( value_type abs_error , value_type rel_error , const stepper_type &stepper )
+ {
+ return controller_type(step_adjuster_type(abs_error, rel_error));
+ }
+
+ controller_type operator()( value_type abs_error , value_type rel_error ,
+ time_type max_dt, const stepper_type &stepper )
+ {
+ return controller_type( step_adjuster_type(abs_error, rel_error, max_dt));
+ }
+};
+
+}
+}
+}
+
+#endif \ No newline at end of file
diff --git a/boost/numeric/odeint/stepper/rosenbrock4_controller.hpp b/boost/numeric/odeint/stepper/rosenbrock4_controller.hpp
index 61d6e51191..5ad1600d61 100644
--- a/boost/numeric/odeint/stepper/rosenbrock4_controller.hpp
+++ b/boost/numeric/odeint/stepper/rosenbrock4_controller.hpp
@@ -200,7 +200,7 @@ public:
-private:
+protected:
template< class StateIn >
bool resize_m_xerr( const StateIn &x )
diff --git a/boost/numeric/odeint/stepper/rosenbrock4_dense_output.hpp b/boost/numeric/odeint/stepper/rosenbrock4_dense_output.hpp
index 6695ba6a97..d296246ae7 100644
--- a/boost/numeric/odeint/stepper/rosenbrock4_dense_output.hpp
+++ b/boost/numeric/odeint/stepper/rosenbrock4_dense_output.hpp
@@ -41,7 +41,8 @@ class rosenbrock4_dense_output
public:
typedef ControlledStepper controlled_stepper_type;
- typedef typename controlled_stepper_type::stepper_type stepper_type;
+ typedef typename unwrap_reference< controlled_stepper_type >::type unwrapped_controlled_stepper_type;
+ typedef typename unwrapped_controlled_stepper_type::stepper_type stepper_type;
typedef typename stepper_type::value_type value_type;
typedef typename stepper_type::state_type state_type;
typedef typename stepper_type::wrapped_state_type wrapped_state_type;
@@ -54,7 +55,7 @@ public:
typedef rosenbrock4_dense_output< ControlledStepper > dense_output_stepper_type;
rosenbrock4_dense_output( const controlled_stepper_type &stepper = controlled_stepper_type() )
- : m_stepper( stepper ) ,
+ : m_stepper( stepper ) ,
m_x1() , m_x2() ,
m_current_state_x1( true ) ,
m_t() , m_t_old() , m_dt()
@@ -75,16 +76,17 @@ public:
template< class System >
std::pair< time_type , time_type > do_step( System system )
{
+ unwrapped_controlled_stepper_type &stepper = m_stepper;
failed_step_checker fail_checker; // to throw a runtime_error if step size adjustment fails
controlled_step_result res = fail;
m_t_old = m_t;
do
{
- res = m_stepper.try_step( system , get_current_state() , m_t , get_old_state() , m_dt );
+ res = stepper.try_step( system , get_current_state() , m_t , get_old_state() , m_dt );
fail_checker(); // check for overflow of failed steps
}
while( res == fail );
- m_stepper.stepper().prepare_dense_output();
+ stepper.stepper().prepare_dense_output();
this->toggle_current_state();
return std::make_pair( m_t_old , m_t );
}
@@ -96,20 +98,23 @@ public:
template< class StateOut >
void calc_state( time_type t , StateOut &x )
{
- m_stepper.stepper().calc_state( t , x , get_old_state() , m_t_old , get_current_state() , m_t );
+ unwrapped_controlled_stepper_type &stepper = m_stepper;
+ stepper.stepper().calc_state( t , x , get_old_state() , m_t_old , get_current_state() , m_t );
}
template< class StateOut >
void calc_state( time_type t , const StateOut &x )
{
- m_stepper.stepper().calc_state( t , x , get_old_state() , m_t_old , get_current_state() , m_t );
+ unwrapped_controlled_stepper_type &stepper = m_stepper;
+ stepper.stepper().calc_state( t , x , get_old_state() , m_t_old , get_current_state() , m_t );
}
template< class StateType >
void adjust_size( const StateType &x )
{
- m_stepper.adjust_size( x );
+ unwrapped_controlled_stepper_type &stepper = m_stepper;
+ stepper.adjust_size( x );
resize_impl( x );
}
diff --git a/boost/outcome.hpp b/boost/outcome.hpp
index 6580107150..2b03ad2357 100644
--- a/boost/outcome.hpp
+++ b/boost/outcome.hpp
@@ -1,5 +1,5 @@
/* Include the default amount of outcome
-(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (4 commits)
File Created: Mar 2018
diff --git a/boost/outcome/bad_access.hpp b/boost/outcome/bad_access.hpp
index 32bdfeae4f..81be36253a 100644
--- a/boost/outcome/bad_access.hpp
+++ b/boost/outcome/bad_access.hpp
@@ -1,5 +1,5 @@
/* Exception types throwable
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (9 commits)
File Created: Oct 2017
diff --git a/boost/outcome/basic_outcome.hpp b/boost/outcome/basic_outcome.hpp
index 0de7c69ad3..25b44d4d3d 100644
--- a/boost/outcome/basic_outcome.hpp
+++ b/boost/outcome/basic_outcome.hpp
@@ -1,5 +1,5 @@
/* A less simple result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
File Created: June 2017
@@ -187,18 +187,20 @@ template <class R, class S, class P, class NoValuePolicy>
BOOST_OUTCOME_REQUIRES(trait::type_can_be_used_in_basic_result<P> && (std::is_void<P>::value || std::is_default_constructible<P>::value)) //
class BOOST_OUTCOME_NODISCARD basic_outcome
#if defined(BOOST_OUTCOME_DOXYGEN_IS_IN_THE_HOUSE) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
-: public detail::basic_outcome_failure_observers<detail::basic_result_final<R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy>,
- public detail::basic_outcome_exception_observers<detail::basic_result_final<R, S, NoValuePolicy>, R, S, P, NoValuePolicy>,
- public detail::basic_result_final<R, S, NoValuePolicy>
+ : public detail::basic_outcome_failure_observers<detail::basic_result_final<R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy>,
+ public detail::basic_outcome_exception_observers<detail::basic_result_final<R, S, NoValuePolicy>, R, S, P, NoValuePolicy>,
+ public detail::basic_result_final<R, S, NoValuePolicy>
#else
-: public detail::select_basic_outcome_failure_observers<detail::basic_outcome_exception_observers<detail::basic_result_final<R, S, NoValuePolicy>, R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy>
+ : public detail::select_basic_outcome_failure_observers<detail::basic_outcome_exception_observers<detail::basic_result_final<R, S, NoValuePolicy>, R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy>
#endif
{
static_assert(trait::type_can_be_used_in_basic_result<P>, "The exception_type cannot be used");
static_assert(std::is_void<P>::value || std::is_default_constructible<P>::value, "exception_type must be void or default constructible");
using base = detail::select_basic_outcome_failure_observers<detail::basic_outcome_exception_observers<detail::basic_result_final<R, S, NoValuePolicy>, R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy>;
friend struct policy::base;
- template <class T, class U, class V, class W> friend class basic_outcome;
+ template <class T, class U, class V, class W> //
+ BOOST_OUTCOME_REQUIRES(trait::type_can_be_used_in_basic_result<V> && (std::is_void<V>::value || std::is_default_constructible<V>::value)) //
+ friend class basic_outcome;
template <class T, class U, class V, class W, class X> friend constexpr inline void hooks::override_outcome_exception(basic_outcome<T, U, V, W> *o, X &&v) noexcept; // NOLINT
struct implicit_constructors_disabled_tag
@@ -362,8 +364,8 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_value_converting_constructor<T>))
constexpr basic_outcome(T &&t, value_converting_constructor_tag /*unused*/ = value_converting_constructor_tag()) noexcept(std::is_nothrow_constructible<value_type, T>::value) // NOLINT
- : base{in_place_type<typename base::_value_type>, static_cast<T &&>(t)},
- _ptr()
+ : base{in_place_type<typename base::_value_type>, static_cast<T &&>(t)}
+ , _ptr()
{
using namespace hooks;
hook_outcome_construction(this, static_cast<T &&>(t));
@@ -374,8 +376,8 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_error_converting_constructor<T>))
constexpr basic_outcome(T &&t, error_converting_constructor_tag /*unused*/ = error_converting_constructor_tag()) noexcept(std::is_nothrow_constructible<error_type, T>::value) // NOLINT
- : base{in_place_type<typename base::_error_type>, static_cast<T &&>(t)},
- _ptr()
+ : base{in_place_type<typename base::_error_type>, static_cast<T &&>(t)}
+ , _ptr()
{
using namespace hooks;
hook_outcome_construction(this, static_cast<T &&>(t));
@@ -387,7 +389,7 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(error_type(make_error_code(ErrorCondEnum()))), //
BOOST_OUTCOME_TPRED(predicate::template enable_error_condition_converting_constructor<ErrorCondEnum>))
constexpr basic_outcome(ErrorCondEnum &&t, error_condition_converting_constructor_tag /*unused*/ = error_condition_converting_constructor_tag()) noexcept(noexcept(error_type(make_error_code(static_cast<ErrorCondEnum &&>(t))))) // NOLINT
- : base{in_place_type<typename base::_error_type>, make_error_code(t)}
+ : base{in_place_type<typename base::_error_type>, make_error_code(t)}
{
using namespace hooks;
hook_outcome_construction(this, static_cast<ErrorCondEnum &&>(t));
@@ -398,8 +400,8 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_exception_converting_constructor<T>))
constexpr basic_outcome(T &&t, exception_converting_constructor_tag /*unused*/ = exception_converting_constructor_tag()) noexcept(std::is_nothrow_constructible<exception_type, T>::value) // NOLINT
- : base(),
- _ptr(static_cast<T &&>(t))
+ : base()
+ , _ptr(static_cast<T &&>(t))
{
using namespace hooks;
this->_state._status |= detail::status_have_exception;
@@ -411,8 +413,8 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T, class U)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_error_exception_converting_constructor<T, U>))
constexpr basic_outcome(T &&a, U &&b, error_exception_converting_constructor_tag /*unused*/ = error_exception_converting_constructor_tag()) noexcept(std::is_nothrow_constructible<error_type, T>::value &&std::is_nothrow_constructible<exception_type, U>::value) // NOLINT
- : base{in_place_type<typename base::_error_type>, static_cast<T &&>(a)},
- _ptr(static_cast<U &&>(b))
+ : base{in_place_type<typename base::_error_type>, static_cast<T &&>(a)}
+ , _ptr(static_cast<U &&>(b))
{
using namespace hooks;
this->_state._status |= detail::status_have_exception;
@@ -427,7 +429,7 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TPRED(convert::value_or_error<basic_outcome, std::decay_t<T>>::enable_outcome_inputs || !is_basic_outcome_v<T>), //
BOOST_OUTCOME_TEXPR(convert::value_or_error<basic_outcome, std::decay_t<T>>{}(std::declval<T>())))
constexpr explicit basic_outcome(T &&o, explicit_valueorerror_converting_constructor_tag /*unused*/ = explicit_valueorerror_converting_constructor_tag()) // NOLINT
- : basic_outcome{convert::value_or_error<basic_outcome, std::decay_t<T>>{}(static_cast<T &&>(o))}
+ : basic_outcome{convert::value_or_error<basic_outcome, std::decay_t<T>>{}(static_cast<T &&>(o))}
{
}
/*! AWAITING HUGO JSON CONVERSION TOOL
@@ -568,7 +570,7 @@ SIGNATURE NOT RECOGNISED
SIGNATURE NOT RECOGNISED
*/
constexpr basic_outcome(const success_type<void> &o) noexcept(std::is_nothrow_default_constructible<value_type>::value) // NOLINT
- : base{in_place_type<typename base::_value_type>}
+ : base{in_place_type<typename base::_value_type>}
{
using namespace hooks;
hook_outcome_copy_construction(this, o);
@@ -579,7 +581,7 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<T, void, void, void>))
constexpr basic_outcome(const success_type<T> &o) noexcept(std::is_nothrow_constructible<value_type, T>::value) // NOLINT
- : base{in_place_type<typename base::_value_type>, detail::extract_value_from_success<value_type>(o)}
+ : base{in_place_type<typename base::_value_type>, detail::extract_value_from_success<value_type>(o)}
{
using namespace hooks;
hook_outcome_copy_construction(this, o);
@@ -590,7 +592,7 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<T, void, void, void>))
constexpr basic_outcome(success_type<T> &&o) noexcept(std::is_nothrow_constructible<value_type, T>::value) // NOLINT
- : base{in_place_type<typename base::_value_type>, detail::extract_value_from_success<value_type>(static_cast<success_type<T> &&>(o))}
+ : base{in_place_type<typename base::_value_type>, detail::extract_value_from_success<value_type>(static_cast<success_type<T> &&>(o))}
{
using namespace hooks;
hook_outcome_move_construction(this, static_cast<success_type<T> &&>(o));
@@ -602,8 +604,8 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, T, void, void>))
constexpr basic_outcome(const failure_type<T> &o, error_failure_tag /*unused*/ = error_failure_tag()) noexcept(std::is_nothrow_constructible<error_type, T>::value) // NOLINT
- : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(o)},
- _ptr()
+ : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(o)}
+ , _ptr()
{
using namespace hooks;
hook_outcome_copy_construction(this, o);
@@ -614,8 +616,8 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, void, T, void>))
constexpr basic_outcome(const failure_type<T> &o, exception_failure_tag /*unused*/ = exception_failure_tag()) noexcept(std::is_nothrow_constructible<exception_type, T>::value) // NOLINT
- : base(),
- _ptr(detail::extract_exception_from_failure<exception_type>(o))
+ : base()
+ , _ptr(detail::extract_exception_from_failure<exception_type>(o))
{
this->_state._status |= detail::status_have_exception;
using namespace hooks;
@@ -627,8 +629,8 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T, class U)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<U>::value && predicate::template enable_compatible_conversion<void, T, U, void>))
constexpr basic_outcome(const failure_type<T, U> &o) noexcept(std::is_nothrow_constructible<error_type, T>::value &&std::is_nothrow_constructible<exception_type, U>::value) // NOLINT
- : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(o)},
- _ptr(detail::extract_exception_from_failure<exception_type>(o))
+ : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(o)}
+ , _ptr(detail::extract_exception_from_failure<exception_type>(o))
{
if(!o.has_error())
{
@@ -648,8 +650,8 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, T, void, void>))
constexpr basic_outcome(failure_type<T> &&o, error_failure_tag /*unused*/ = error_failure_tag()) noexcept(std::is_nothrow_constructible<error_type, T>::value) // NOLINT
- : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o))},
- _ptr()
+ : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o))}
+ , _ptr()
{
using namespace hooks;
hook_outcome_copy_construction(this, o);
@@ -660,8 +662,8 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, void, T, void>))
constexpr basic_outcome(failure_type<T> &&o, exception_failure_tag /*unused*/ = exception_failure_tag()) noexcept(std::is_nothrow_constructible<exception_type, T>::value) // NOLINT
- : base(),
- _ptr(detail::extract_exception_from_failure<exception_type>(static_cast<failure_type<T> &&>(o)))
+ : base()
+ , _ptr(detail::extract_exception_from_failure<exception_type>(static_cast<failure_type<T> &&>(o)))
{
this->_state._status |= detail::status_have_exception;
using namespace hooks;
@@ -673,8 +675,8 @@ SIGNATURE NOT RECOGNISED
BOOST_OUTCOME_TEMPLATE(class T, class U)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<U>::value && predicate::template enable_compatible_conversion<void, T, U, void>))
constexpr basic_outcome(failure_type<T, U> &&o) noexcept(std::is_nothrow_constructible<error_type, T>::value &&std::is_nothrow_constructible<exception_type, U>::value) // NOLINT
- : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T, U> &&>(o))},
- _ptr(detail::extract_exception_from_failure<exception_type>(static_cast<failure_type<T, U> &&>(o)))
+ : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T, U> &&>(o))}
+ , _ptr(detail::extract_exception_from_failure<exception_type>(static_cast<failure_type<T, U> &&>(o)))
{
if(!o.has_error())
{
@@ -807,110 +809,83 @@ SIGNATURE NOT RECOGNISED
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
- void swap(basic_outcome &o) noexcept(detail::is_nothrow_swappable<value_type>::value &&std::is_nothrow_move_constructible<value_type>::value //
- &&detail::is_nothrow_swappable<error_type>::value &&std::is_nothrow_move_constructible<error_type>::value //
- &&detail::is_nothrow_swappable<exception_type>::value &&std::is_nothrow_move_constructible<exception_type>::value)
+ constexpr void swap(basic_outcome &o) noexcept((std::is_void<value_type>::value || detail::is_nothrow_swappable<value_type>::value) //
+ && (std::is_void<error_type>::value || detail::is_nothrow_swappable<error_type>::value) //
+ && (std::is_void<exception_type>::value || detail::is_nothrow_swappable<exception_type>::value))
{
- using std::swap;
#ifndef BOOST_NO_EXCEPTIONS
- constexpr bool value_throws = !noexcept(this->_state.swap(o._state));
- constexpr bool error_throws = !noexcept(swap(this->_error, o._error));
- constexpr bool exception_throws = !noexcept(swap(this->_ptr, o._ptr));
+ constexpr bool value_throws = !std::is_void<value_type>::value && !detail::is_nothrow_swappable<value_type>::value;
+ constexpr bool error_throws = !std::is_void<error_type>::value && !detail::is_nothrow_swappable<error_type>::value;
+ constexpr bool exception_throws = !std::is_void<exception_type>::value && !detail::is_nothrow_swappable<exception_type>::value;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#endif
- // Do throwing swap first
- if((value_throws && !error_throws && !exception_throws) || (!value_throws && !error_throws && !exception_throws))
- {
- this->_state.swap(o._state);
- swap(this->_error, o._error);
- swap(this->_ptr, o._ptr);
- }
- else if(!value_throws && !error_throws && exception_throws)
- {
- swap(this->_ptr, o._ptr);
- this->_state.swap(o._state);
- swap(this->_error, o._error);
- }
- else if(!value_throws && error_throws && !exception_throws)
+ if(!exception_throws && !value_throws && !error_throws)
{
- swap(this->_error, o._error);
- this->_state.swap(o._state);
+ // Simples
+ detail::basic_result_storage_swap<value_throws, error_throws>(*this, o);
+ using std::swap;
swap(this->_ptr, o._ptr);
+ return;
}
- else
+ struct _
{
- // Two or more can throw
- this->_state.swap(o._state);
- bool exception_threw = false;
- try
+ basic_outcome &a, &b;
+ bool exceptioned{false};
+ bool all_good{false};
+ ~_()
{
- swap(this->_error, o._error);
- exception_threw = true;
- swap(this->_ptr, o._ptr);
- }
- catch(...)
- {
- // Try to put it back
- bool error_is_mine = !exception_threw;
- try
+ if(!all_good)
{
- if(exception_threw)
- {
- swap(this->_error, o._error);
- error_is_mine = true;
- }
- this->_state.swap(o._state);
- // If that succeeded, continue by rethrowing the exception
+ // We lost one of the values
+ a._state._status |= detail::status_lost_consistency;
+ b._state._status |= detail::status_lost_consistency;
+ return;
}
- catch(...)
+ if(exceptioned)
{
- if(error_is_mine)
+ // The value + error swap threw an exception. Try to swap back _ptr
+ try
{
- try
- {
- swap(this->_error, o._error);
- error_is_mine = false;
- }
- catch(...)
- {
- }
+ strong_swap(all_good, a._ptr, b._ptr);
+ }
+ catch(...)
+ {
+ // We lost one of the values
+ a._state._status |= detail::status_lost_consistency;
+ b._state._status |= detail::status_lost_consistency;
+ // throw away second exception
}
+
// Prevent has_value() == has_error() or has_value() == has_exception()
- auto check = [](basic_outcome *t, bool set_error) {
+ auto check = [](basic_outcome *t) {
if(t->has_value() && (t->has_error() || t->has_exception()))
{
- // We know the value swapped and is now set, so clear error and exception
t->_state._status &= ~(detail::status_have_error | detail::status_have_exception);
+ t->_state._status |= detail::status_lost_consistency;
}
if(!t->has_value() && !(t->has_error() || t->has_exception()))
{
- // We know the value swapped and is now unset, so either set exception or error
- if(set_error)
- {
- t->_state._status |= detail::status_have_error;
- }
- else
- {
- t->_state._status |= detail::status_have_exception;
- }
+ // Choose error, for no particular reason
+ t->_state._status |= detail::status_have_error | detail::status_lost_consistency;
}
};
- // If my value is unset and error is not mine, set error
- check(this, !error_is_mine);
- // If other's value is unset and error is not mine, set error
- check(&o, !error_is_mine);
+ check(&a);
+ check(&b);
}
- throw;
}
- }
+ } _{*this, o};
+ strong_swap(_.all_good, this->_ptr, o._ptr);
+ _.exceptioned = true;
+ detail::basic_result_storage_swap<value_throws, error_throws>(*this, o);
+ _.exceptioned = false;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#else
- this->_state.swap(o._state);
- swap(this->_error, o._error);
+ detail::basic_result_storage_swap<false, false>(*this, o);
+ using std::swap;
swap(this->_ptr, o._ptr);
#endif
}
diff --git a/boost/outcome/basic_result.hpp b/boost/outcome/basic_result.hpp
index 7d51341152..db3cb5218a 100644
--- a/boost/outcome/basic_result.hpp
+++ b/boost/outcome/basic_result.hpp
@@ -1,5 +1,5 @@
/* A very simple result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (14 commits)
File Created: June 2017
@@ -503,12 +503,11 @@ SIGNATURE NOT RECOGNISED
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
- constexpr void swap(basic_result &o) noexcept(detail::is_nothrow_swappable<value_type>::value &&std::is_nothrow_move_constructible<value_type>::value //
- &&detail::is_nothrow_swappable<error_type>::value &&std::is_nothrow_move_constructible<error_type>::value)
+ constexpr void swap(basic_result &o) noexcept((std::is_void<value_type>::value || detail::is_nothrow_swappable<value_type>::value) //
+ &&(std::is_void<error_type>::value || detail::is_nothrow_swappable<error_type>::value))
{
- using std::swap;
- constexpr bool value_throws = !noexcept(this->_state.swap(o._state));
- constexpr bool error_throws = !noexcept(swap(this->_error, o._error));
+ constexpr bool value_throws = !std::is_void<value_type>::value && !detail::is_nothrow_swappable<value_type>::value;
+ constexpr bool error_throws = !std::is_void<error_type>::value && !detail::is_nothrow_swappable<error_type>::value;
detail::basic_result_storage_swap<value_throws, error_throws>(*this, o);
}
diff --git a/boost/outcome/boost_outcome.hpp b/boost/outcome/boost_outcome.hpp
index d45d998484..23789603fc 100644
--- a/boost/outcome/boost_outcome.hpp
+++ b/boost/outcome/boost_outcome.hpp
@@ -1,5 +1,5 @@
/* A less simple result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (7 commits)
File Created: June 2017
@@ -35,6 +35,8 @@ DEALINGS IN THE SOFTWARE.
#include "boost_result.hpp"
+#ifndef BOOST_SYSTEM_BASIC_OUTCOME_FAILURE_EXCEPTION_FROM_ERROR
+#define BOOST_SYSTEM_BASIC_OUTCOME_FAILURE_EXCEPTION_FROM_ERROR
namespace boost
{
namespace system
@@ -43,6 +45,7 @@ namespace boost
inline boost::exception_ptr basic_outcome_failure_exception_from_error(const boost::system::error_code &ec) { return boost::copy_exception(boost::system::system_error(ec)); }
} // namespace system
} // namespace boost
+#endif
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
diff --git a/boost/outcome/boost_result.hpp b/boost/outcome/boost_result.hpp
index 55c324f0d7..25ebc2a67c 100644
--- a/boost/outcome/boost_result.hpp
+++ b/boost/outcome/boost_result.hpp
@@ -1,5 +1,5 @@
/* A very simple result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (10 commits)
File Created: June 2017
diff --git a/boost/outcome/config.hpp b/boost/outcome/config.hpp
index 9ed802cbec..0444a2a4c2 100644
--- a/boost/outcome/config.hpp
+++ b/boost/outcome/config.hpp
@@ -1,5 +1,5 @@
/* Configure Boost.Outcome with Boost
-(C) 2015-2019 Niall Douglas <http://www.nedproductions.biz/> (24 commits)
+(C) 2015-2019 Niall Douglas <http://www.nedproductions.biz/> (7 commits)
File Created: August 2015
@@ -31,7 +31,7 @@ DEALINGS IN THE SOFTWARE.
#ifndef BOOST_OUTCOME_V2_CONFIG_HPP
#define BOOST_OUTCOME_V2_CONFIG_HPP
-#include "version.hpp"
+#include "detail/version.hpp"
// Pull in detection of __MINGW64_VERSION_MAJOR
#if defined(__MINGW32__) && !defined(DOXYGEN_IS_IN_THE_HOUSE)
@@ -295,18 +295,10 @@ namespace detail
#if !defined(STANDARDESE_IS_IN_THE_HOUSE) && BOOST_OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE
template <class T> using is_nothrow_swappable = std::is_nothrow_swappable<T>;
#else
- namespace _is_nothrow_swappable
+ template <class T> struct is_nothrow_swappable
{
- using namespace std;
- template <class T> constexpr inline T &ldeclval();
- template <class T, class = void> struct is_nothrow_swappable : std::integral_constant<bool, false>
- {
- };
- template <class T> struct is_nothrow_swappable<T, decltype(swap(ldeclval<T>(), ldeclval<T>()))> : std::integral_constant<bool, noexcept(swap(ldeclval<T>(), ldeclval<T>()))>
- {
- };
- } // namespace _is_nothrow_swappable
- template <class T> using is_nothrow_swappable = _is_nothrow_swappable::is_nothrow_swappable<T>;
+ static constexpr bool value = std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value;
+ };
#endif
} // namespace detail
BOOST_OUTCOME_V2_NAMESPACE_END
diff --git a/boost/outcome/convert.hpp b/boost/outcome/convert.hpp
index 26cd6cc623..20d13ef28f 100644
--- a/boost/outcome/convert.hpp
+++ b/boost/outcome/convert.hpp
@@ -1,5 +1,5 @@
/* Says how to convert value, error and exception types
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
File Created: Nov 2017
@@ -38,10 +38,15 @@ BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace convert
{
#if defined(__cpp_concepts)
+#if !defined(_MSC_VER) && !defined(__clang__) && __GNUC__ < 8
+#define BOOST_OUTCOME_GCC6_CONCEPT_BOOL bool
+#else
+#define BOOST_OUTCOME_GCC6_CONCEPT_BOOL
+#endif
/* The `ValueOrNone` concept.
\requires That `U::value_type` exists and that `std::declval<U>().has_value()` returns a `bool` and `std::declval<U>().value()` exists.
*/
- template <class U> concept bool ValueOrNone = requires(U a)
+ template <class U> concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL ValueOrNone = requires(U a)
{
{
a.has_value()
@@ -53,7 +58,7 @@ namespace convert
\requires That `U::value_type` and `U::error_type` exist;
that `std::declval<U>().has_value()` returns a `bool`, `std::declval<U>().value()` and `std::declval<U>().error()` exists.
*/
- template <class U> concept bool ValueOrError = requires(U a)
+ template <class U> concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL ValueOrError = requires(U a)
{
{
a.has_value()
@@ -107,7 +112,7 @@ namespace convert
};
} // namespace detail
- /*! AWAITING HUGO JSON CONVERSION TOOL
+ /*! AWAITING HUGO JSON CONVERSION TOOL
type definition value_or_error. Potential doc page: NOT FOUND
*/
template <class T, class U> struct value_or_error
diff --git a/boost/outcome/detail/basic_outcome_exception_observers.hpp b/boost/outcome/detail/basic_outcome_exception_observers.hpp
index 45efa5d246..e2f0365f29 100644
--- a/boost/outcome/detail/basic_outcome_exception_observers.hpp
+++ b/boost/outcome/detail/basic_outcome_exception_observers.hpp
@@ -1,5 +1,5 @@
/* Exception observers for outcome type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (3 commits)
File Created: Oct 2017
diff --git a/boost/outcome/detail/basic_outcome_exception_observers_impl.hpp b/boost/outcome/detail/basic_outcome_exception_observers_impl.hpp
index cc4ec18210..2f0f238091 100644
--- a/boost/outcome/detail/basic_outcome_exception_observers_impl.hpp
+++ b/boost/outcome/detail/basic_outcome_exception_observers_impl.hpp
@@ -1,5 +1,5 @@
/* Exception observers for outcome type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
File Created: Oct 2017
diff --git a/boost/outcome/detail/basic_outcome_failure_observers.hpp b/boost/outcome/detail/basic_outcome_failure_observers.hpp
index 860a613d1a..365f141620 100644
--- a/boost/outcome/detail/basic_outcome_failure_observers.hpp
+++ b/boost/outcome/detail/basic_outcome_failure_observers.hpp
@@ -1,5 +1,5 @@
/* Failure observers for outcome type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (7 commits)
File Created: Oct 2017
diff --git a/boost/outcome/detail/basic_result_error_observers.hpp b/boost/outcome/detail/basic_result_error_observers.hpp
index a883602502..dcc7fa7906 100644
--- a/boost/outcome/detail/basic_result_error_observers.hpp
+++ b/boost/outcome/detail/basic_result_error_observers.hpp
@@ -1,5 +1,5 @@
/* Error observers for a very simple basic_result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
File Created: Oct 2017
diff --git a/boost/outcome/detail/basic_result_final.hpp b/boost/outcome/detail/basic_result_final.hpp
index bc3864c4c0..0fedea146a 100644
--- a/boost/outcome/detail/basic_result_final.hpp
+++ b/boost/outcome/detail/basic_result_final.hpp
@@ -1,5 +1,5 @@
/* Finaliser for a very simple result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Oct 2017
@@ -57,6 +57,7 @@ namespace detail
constexpr bool has_value() const noexcept { return (this->_state._status & detail::status_have_value) != 0; }
constexpr bool has_error() const noexcept { return (this->_state._status & detail::status_have_error) != 0; }
constexpr bool has_exception() const noexcept { return (this->_state._status & detail::status_have_exception) != 0; }
+ constexpr bool has_lost_consistency() const noexcept { return (this->_state._status & detail::status_lost_consistency) != 0; }
constexpr bool has_failure() const noexcept { return (this->_state._status & detail::status_have_error) != 0 || (this->_state._status & detail::status_have_exception) != 0; }
BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
diff --git a/boost/outcome/detail/basic_result_storage.hpp b/boost/outcome/detail/basic_result_storage.hpp
index a04b4d2ac7..f25e49ebc1 100644
--- a/boost/outcome/detail/basic_result_storage.hpp
+++ b/boost/outcome/detail/basic_result_storage.hpp
@@ -1,5 +1,5 @@
/* Storage for a very simple basic_result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
File Created: Oct 2017
@@ -59,6 +59,9 @@ namespace detail
template <bool value_throws, bool error_throws> struct basic_result_storage_swap;
template <class R, class EC, class NoValuePolicy> //
BOOST_OUTCOME_REQUIRES(trait::type_can_be_used_in_basic_result<R> &&trait::type_can_be_used_in_basic_result<EC> && (std::is_void<EC>::value || std::is_default_constructible<EC>::value)) //
+ class basic_result_storage;
+ template <class R, class EC, class NoValuePolicy> //
+ BOOST_OUTCOME_REQUIRES(trait::type_can_be_used_in_basic_result<R> &&trait::type_can_be_used_in_basic_result<EC> && (std::is_void<EC>::value || std::is_default_constructible<EC>::value)) //
class basic_result_storage
{
static_assert(trait::type_can_be_used_in_basic_result<R>, "The type R cannot be used in a basic_result");
@@ -66,7 +69,9 @@ namespace detail
static_assert(std::is_void<EC>::value || std::is_default_constructible<EC>::value, "The type S must be void or default constructible");
friend struct policy::base;
- template <class T, class U, class V> friend class basic_result_storage;
+ template <class T, class U, class V> //
+ BOOST_OUTCOME_REQUIRES(trait::type_can_be_used_in_basic_result<T> &&trait::type_can_be_used_in_basic_result<U> && (std::is_void<U>::value || std::is_default_constructible<U>::value)) //
+ friend class basic_result_storage;
template <class T, class U, class V> friend class basic_result_final;
template <class T, class U, class V> friend constexpr inline uint16_t hooks::spare_storage(const detail::basic_result_final<T, U, V> *r) noexcept; // NOLINT
template <class T, class U, class V> friend constexpr inline void hooks::set_spare_storage(detail::basic_result_final<T, U, V> *r, uint16_t v) noexcept; // NOLINT
@@ -192,8 +197,21 @@ namespace detail
{
template <class R, class EC, class NoValuePolicy> constexpr basic_result_storage_swap(basic_result_storage<R, EC, NoValuePolicy> &a, basic_result_storage<R, EC, NoValuePolicy> &b)
{
- using std::swap;
- swap(a._msvc_nonpermissive_error(), b._msvc_nonpermissive_error());
+ struct _
+ {
+ unsigned &a, &b;
+ bool all_good{false};
+ ~_()
+ {
+ if(!all_good)
+ {
+ // We lost one of the values
+ a |= status_lost_consistency;
+ b |= status_lost_consistency;
+ }
+ }
+ } _{a._msvc_nonpermissive_state()._status, b._msvc_nonpermissive_state()._status};
+ strong_swap(_.all_good, a._msvc_nonpermissive_error(), b._msvc_nonpermissive_error());
a._msvc_nonpermissive_state().swap(b._msvc_nonpermissive_state());
}
};
@@ -205,19 +223,33 @@ namespace detail
using std::swap;
// Swap value and status first, if it throws, status will remain unchanged
a._msvc_nonpermissive_state().swap(b._msvc_nonpermissive_state());
+ bool all_good = false;
try
{
- swap(a._msvc_nonpermissive_error(), b._msvc_nonpermissive_error());
+ strong_swap(all_good, a._msvc_nonpermissive_error(), b._msvc_nonpermissive_error());
}
catch(...)
{
- // First try to put the value and status back
- try
+ if(!all_good)
+ {
+ a._msvc_nonpermissive_state()._status |= detail::status_lost_consistency;
+ b._msvc_nonpermissive_state()._status |= detail::status_lost_consistency;
+ }
+ else
{
- a._msvc_nonpermissive_state().swap(b._msvc_nonpermissive_state());
- // If that succeeded, continue by rethrowing the exception
+ // We may still be able to rescue tis
+ // First try to put the value and status back
+ try
+ {
+ a._msvc_nonpermissive_state().swap(b._msvc_nonpermissive_state());
+ // If that succeeded, continue by rethrowing the exception
+ }
+ catch(...)
+ {
+ all_good = false;
+ }
}
- catch(...)
+ if(!all_good)
{
// We are now trapped. The value swapped, the error did not,
// trying to restore the value failed. We now have
@@ -227,6 +259,7 @@ namespace detail
bool has_value = (x._state._status & detail::status_have_value) != 0;
bool has_error = (x._state._status & detail::status_have_error) != 0;
bool has_exception = (x._state._status & detail::status_have_exception) != 0;
+ x._state._status |= detail::status_lost_consistency;
if(has_value == (has_error || has_exception))
{
if(has_value)
diff --git a/boost/outcome/detail/basic_result_value_observers.hpp b/boost/outcome/detail/basic_result_value_observers.hpp
index c062e9e5db..9f17a3b257 100644
--- a/boost/outcome/detail/basic_result_value_observers.hpp
+++ b/boost/outcome/detail/basic_result_value_observers.hpp
@@ -1,5 +1,5 @@
/* Value observers for a very simple basic_result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
File Created: Oct 2017
diff --git a/boost/outcome/detail/revision.hpp b/boost/outcome/detail/revision.hpp
new file mode 100644
index 0000000000..5d2acb5f9f
--- /dev/null
+++ b/boost/outcome/detail/revision.hpp
@@ -0,0 +1,33 @@
+/* UPDATED BY SCRIPT
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (225 commits)
+
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
+#define BOOST_OUTCOME_PREVIOUS_COMMIT_REF b29bef8186ac800d3281c88b0107d7bee9652603
+#define BOOST_OUTCOME_PREVIOUS_COMMIT_DATE "2019-08-13 12:21:10 +00:00"
+#define BOOST_OUTCOME_PREVIOUS_COMMIT_UNIQUE b29bef81
diff --git a/boost/outcome/detail/trait_std_error_code.hpp b/boost/outcome/detail/trait_std_error_code.hpp
index c813b47836..68ea7bd380 100644
--- a/boost/outcome/detail/trait_std_error_code.hpp
+++ b/boost/outcome/detail/trait_std_error_code.hpp
@@ -1,5 +1,5 @@
/* Traits for Outcome
-(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
File Created: March 2018
diff --git a/boost/outcome/detail/trait_std_exception.hpp b/boost/outcome/detail/trait_std_exception.hpp
index ec9df2cdcf..f610a8667b 100644
--- a/boost/outcome/detail/trait_std_exception.hpp
+++ b/boost/outcome/detail/trait_std_exception.hpp
@@ -1,5 +1,5 @@
/* Traits for Outcome
-(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (3 commits)
File Created: March 2018
diff --git a/boost/outcome/detail/value_storage.hpp b/boost/outcome/detail/value_storage.hpp
index 5f148f3eb5..0f7fd6beb5 100644
--- a/boost/outcome/detail/value_storage.hpp
+++ b/boost/outcome/detail/value_storage.hpp
@@ -1,5 +1,5 @@
/* Essentially an internal optional implementation :)
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (24 commits)
File Created: June 2017
@@ -37,13 +37,88 @@ BOOST_OUTCOME_V2_NAMESPACE_BEGIN
namespace detail
{
+ template <class T, bool nothrow> struct strong_swap_impl
+ {
+ constexpr strong_swap_impl(bool &allgood, T &a, T &b)
+ {
+ allgood = true;
+ using std::swap;
+ swap(a, b);
+ }
+ };
+#ifndef BOOST_NO_EXCEPTIONS
+ template <class T> struct strong_swap_impl<T, false>
+ {
+ strong_swap_impl(bool &allgood, T &a, T &b)
+ {
+ allgood = true;
+ T v(static_cast<T &&>(a));
+ try
+ {
+ a = static_cast<T &&>(b);
+ }
+ catch(...)
+ {
+ // Try to put back a
+ try
+ {
+ a = static_cast<T &&>(v);
+ // fall through as all good
+ }
+ catch(...)
+ {
+ // failed to completely restore
+ allgood = false;
+ // throw away second exception
+ }
+ throw; // rethrow original exception
+ }
+ // b has been moved to a, try to move v to b
+ try
+ {
+ b = static_cast<T &&>(v);
+ }
+ catch(...)
+ {
+ // Try to restore a to b, and v to a
+ try
+ {
+ b = static_cast<T &&>(a);
+ a = static_cast<T &&>(v);
+ // fall through as all good
+ }
+ catch(...)
+ {
+ // failed to completely restore
+ allgood = false;
+ // throw away second exception
+ }
+ throw; // rethrow original exception
+ }
+ }
+ };
+#endif
+} // namespace detail
+
+/*!
+ */
+BOOST_OUTCOME_TEMPLATE(class T)
+BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_move_constructible<T>::value &&std::is_move_assignable<T>::value))
+constexpr inline void strong_swap(bool &allgood, T &a, T &b) noexcept(detail::is_nothrow_swappable<T>::value)
+{
+ detail::strong_swap_impl<T, detail::is_nothrow_swappable<T>::value>(allgood, a, b);
+}
+
+namespace detail
+{
using status_bitfield_type = uint32_t;
// WARNING: These bits are not tracked by abi-dumper, but changing them will break ABI!
static constexpr status_bitfield_type status_have_value = (1U << 0U);
static constexpr status_bitfield_type status_have_error = (1U << 1U);
static constexpr status_bitfield_type status_have_exception = (1U << 2U);
- static constexpr status_bitfield_type status_error_is_errno = (1U << 4U); // can errno be set from this error?
+ static constexpr status_bitfield_type status_lost_consistency = (1U << 3U); // failed to complete a strong swap
+ static constexpr status_bitfield_type status_error_is_errno = (1U << 4U); // can errno be set from this error?
// bit 7 unused
// bits 8-15 unused
// bits 16-31 used for user supplied 16 bit value
@@ -59,7 +134,10 @@ namespace detail
devoid<T> _value;
};
status_bitfield_type _status{0};
- constexpr value_storage_trivial() noexcept : _empty{} {}
+ constexpr value_storage_trivial() noexcept
+ : _empty{}
+ {
+ }
// Special from-void catchall constructor, always constructs default T irrespective of whether void is valued or not (can do no better if T cannot be copied)
struct disable_void_catchall
{
@@ -124,11 +202,14 @@ namespace detail
value_type _value;
};
status_bitfield_type _status{0};
- value_storage_nontrivial() noexcept : _empty{} {}
+ value_storage_nontrivial() noexcept
+ : _empty{}
+ {
+ }
value_storage_nontrivial &operator=(const value_storage_nontrivial &) = default; // if reaches here, copy assignment is trivial
value_storage_nontrivial &operator=(value_storage_nontrivial &&) = default; // NOLINT if reaches here, move assignment is trivial
value_storage_nontrivial(value_storage_nontrivial &&o) noexcept(std::is_nothrow_move_constructible<value_type>::value) // NOLINT
- : _status(o._status)
+ : _status(o._status)
{
if(this->_status & status_have_value)
{
@@ -212,7 +293,7 @@ namespace detail
this->_status &= ~status_have_value;
}
}
- constexpr void swap(value_storage_nontrivial &o) noexcept(detail::is_nothrow_swappable<value_type>::value &&std::is_nothrow_move_constructible<value_type>::value)
+ constexpr void swap(value_storage_nontrivial &o) noexcept(detail::is_nothrow_swappable<value_type>::value)
{
using std::swap;
if((_status & status_have_value) == 0 && (o._status & status_have_value) == 0)
@@ -222,7 +303,21 @@ namespace detail
}
if((_status & status_have_value) != 0 && (o._status & status_have_value) != 0)
{
- swap(_value, o._value); // NOLINT
+ struct _
+ {
+ unsigned &a, &b;
+ bool all_good{false};
+ ~_()
+ {
+ if(!all_good)
+ {
+ // We lost one of the values
+ a |= status_lost_consistency;
+ b |= status_lost_consistency;
+ }
+ }
+ } _{_status, o._status};
+ strong_swap(_.all_good, _value, o._value);
swap(_status, o._status);
return;
}
diff --git a/boost/outcome/detail/version.hpp b/boost/outcome/detail/version.hpp
new file mode 100644
index 0000000000..dc62b8182e
--- /dev/null
+++ b/boost/outcome/detail/version.hpp
@@ -0,0 +1,42 @@
+/* Sets Outcome version
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (4 commits)
+
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+/*! AWAITING HUGO JSON CONVERSION TOOL */
+#define BOOST_OUTCOME_VERSION_MAJOR 2
+/*! AWAITING HUGO JSON CONVERSION TOOL */
+#define BOOST_OUTCOME_VERSION_MINOR 1
+/*! AWAITING HUGO JSON CONVERSION TOOL */
+#define BOOST_OUTCOME_VERSION_PATCH 1
+/*! AWAITING HUGO JSON CONVERSION TOOL */
+#define BOOST_OUTCOME_VERSION_REVISION 0 // Revision version for cmake and DLL version stamping
+
+/*! AWAITING HUGO JSON CONVERSION TOOL */
+#ifndef BOOST_OUTCOME_DISABLE_ABI_PERMUTATION
+#define BOOST_OUTCOME_UNSTABLE_VERSION
+#endif
diff --git a/boost/outcome/experimental/result.h b/boost/outcome/experimental/result.h
index dd06ce4b68..53f74ec3d5 100644
--- a/boost/outcome/experimental/result.h
+++ b/boost/outcome/experimental/result.h
@@ -1,5 +1,5 @@
/* C interface for result
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
File Created: Aug 2017
diff --git a/boost/outcome/experimental/status-code/config.hpp b/boost/outcome/experimental/status-code/config.hpp
index 6294041afb..08e21998f7 100644
--- a/boost/outcome/experimental/status-code/config.hpp
+++ b/boost/outcome/experimental/status-code/config.hpp
@@ -160,13 +160,17 @@ namespace detail
Our bit_cast is only guaranteed to be constexpr when both the input and output
arguments are either integrals or enums. However, this covers most use cases
since the vast majority of status_codes have an underlying type that is either
- an integral or enum.
+ an integral or enum. We still attempt a constexpr union-based type pun for non-array
+ input types, which some compilers accept. For array inputs, we fall back to
+ non-constexpr memmove.
*/
template <class T> using is_integral_or_enum = std::integral_constant<bool, std::is_integral<T>::value || std::is_enum<T>::value>;
template <class To, class From> using is_static_castable = std::integral_constant<bool, is_integral_or_enum<To>::value && is_integral_or_enum<From>::value>;
+ template <class To, class From> using is_union_castable = std::integral_constant<bool, !is_static_castable<To, From>::value && !std::is_array<To>::value && !std::is_array<From>::value>;
+
template <class To, class From> using is_bit_castable = std::integral_constant<bool, sizeof(To) == sizeof(From) && traits::is_move_relocating<To>::value && traits::is_move_relocating<From>::value>;
template <class To, class From> union bit_cast_union {
@@ -174,9 +178,40 @@ namespace detail
To target;
};
- template <class To, class From, typename std::enable_if<is_bit_castable<To, From>::value && is_static_castable<To, From>::value, bool>::type = true> constexpr To bit_cast(const From &from) noexcept { return static_cast<To>(from); }
+ template <class To, class From,
+ typename std::enable_if< //
+ is_bit_castable<To, From>::value //
+ && is_static_castable<To, From>::value //
+ && !is_union_castable<To, From>::value, //
+ bool>::type = true> //
+ constexpr To bit_cast(const From &from) noexcept
+ {
+ return static_cast<To>(from);
+ }
- template <class To, class From, typename std::enable_if<is_bit_castable<To, From>::value && !is_static_castable<To, From>::value, bool>::type = true> constexpr To bit_cast(const From &from) noexcept { return bit_cast_union<To, From>{from}.target; }
+ template <class To, class From,
+ typename std::enable_if< //
+ is_bit_castable<To, From>::value //
+ && !is_static_castable<To, From>::value //
+ && is_union_castable<To, From>::value, //
+ bool>::type = true> //
+ constexpr To bit_cast(const From &from) noexcept
+ {
+ return bit_cast_union<To, From>{from}.target;
+ }
+
+ template <class To, class From,
+ typename std::enable_if< //
+ is_bit_castable<To, From>::value //
+ && !is_static_castable<To, From>::value //
+ && !is_union_castable<To, From>::value, //
+ bool>::type = true> //
+ To bit_cast(const From &from) noexcept
+ {
+ bit_cast_union<To, From> ret;
+ memmove(&ret.source, &from, sizeof(ret.source));
+ return ret.target;
+ }
/* erasure_cast performs a bit_cast with additional rules to handle types
of differing sizes. For integral & enum types, it may perform a narrowing
@@ -244,7 +279,7 @@ namespace detail
#ifndef __APPLE__
extern "C" ptrdiff_t write(int, const void *, size_t);
#endif
- }
+ } // namespace avoid_stdio_include
inline void do_fatal_exit(const char *msg)
{
using namespace avoid_stdio_include;
diff --git a/boost/outcome/experimental/status_outcome.hpp b/boost/outcome/experimental/status_outcome.hpp
index 8609c790b5..0df4257fc5 100644
--- a/boost/outcome/experimental/status_outcome.hpp
+++ b/boost/outcome/experimental/status_outcome.hpp
@@ -1,5 +1,5 @@
/* A less simple result type
-(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (17 commits)
File Created: Apr 2018
diff --git a/boost/outcome/experimental/status_result.hpp b/boost/outcome/experimental/status_result.hpp
index f7d5b51dca..9f362d6fa7 100644
--- a/boost/outcome/experimental/status_result.hpp
+++ b/boost/outcome/experimental/status_result.hpp
@@ -1,5 +1,5 @@
/* A very simple result type
-(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
File Created: Apr 2018
diff --git a/boost/outcome/iostream_support.hpp b/boost/outcome/iostream_support.hpp
index ac52eda504..607e7184b1 100644
--- a/boost/outcome/iostream_support.hpp
+++ b/boost/outcome/iostream_support.hpp
@@ -1,5 +1,5 @@
/* iostream specialisations for result and outcome
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (21 commits)
File Created: July 2017
diff --git a/boost/outcome/outcome.hpp b/boost/outcome/outcome.hpp
index 09df187cfd..ca0cdcafcf 100644
--- a/boost/outcome/outcome.hpp
+++ b/boost/outcome/outcome.hpp
@@ -1,5 +1,5 @@
/* A less simple result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (1 commit)
File Created: June 2017
diff --git a/boost/outcome/policy/all_narrow.hpp b/boost/outcome/policy/all_narrow.hpp
index bdf7de1ad2..f470c65025 100644
--- a/boost/outcome/policy/all_narrow.hpp
+++ b/boost/outcome/policy/all_narrow.hpp
@@ -1,5 +1,5 @@
/* Policies for result and outcome
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (13 commits)
File Created: Oct 2017
diff --git a/boost/outcome/policy/base.hpp b/boost/outcome/policy/base.hpp
index 4705f00f2a..0c218c1e4e 100644
--- a/boost/outcome/policy/base.hpp
+++ b/boost/outcome/policy/base.hpp
@@ -1,5 +1,5 @@
/* Policies for result and outcome
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (6 commits) and Andrzej Krzemieński <akrzemi1@gmail.com> (1 commit)
File Created: Oct 2017
diff --git a/boost/outcome/policy/fail_to_compile_observers.hpp b/boost/outcome/policy/fail_to_compile_observers.hpp
index ac41ac13c5..0dbf7bf8ff 100644
--- a/boost/outcome/policy/fail_to_compile_observers.hpp
+++ b/boost/outcome/policy/fail_to_compile_observers.hpp
@@ -1,5 +1,5 @@
/* Policies for result and outcome
-(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (4 commits)
File Created: Sep 2018
diff --git a/boost/outcome/policy/outcome_error_code_throw_as_system_error.hpp b/boost/outcome/policy/outcome_error_code_throw_as_system_error.hpp
index 324be7bd11..21b1773429 100644
--- a/boost/outcome/policy/outcome_error_code_throw_as_system_error.hpp
+++ b/boost/outcome/policy/outcome_error_code_throw_as_system_error.hpp
@@ -1,5 +1,5 @@
/* Policies for result and outcome
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
File Created: Oct 2017
diff --git a/boost/outcome/policy/outcome_exception_ptr_rethrow.hpp b/boost/outcome/policy/outcome_exception_ptr_rethrow.hpp
index f0f79ed3e0..44eb83edcd 100644
--- a/boost/outcome/policy/outcome_exception_ptr_rethrow.hpp
+++ b/boost/outcome/policy/outcome_exception_ptr_rethrow.hpp
@@ -1,5 +1,5 @@
/* Policies for result and outcome
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (10 commits)
File Created: Oct 2017
diff --git a/boost/outcome/policy/result_error_code_throw_as_system_error.hpp b/boost/outcome/policy/result_error_code_throw_as_system_error.hpp
index 1bfe85b731..9e17ca1371 100644
--- a/boost/outcome/policy/result_error_code_throw_as_system_error.hpp
+++ b/boost/outcome/policy/result_error_code_throw_as_system_error.hpp
@@ -1,5 +1,5 @@
/* Policies for result and outcome
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (8 commits)
File Created: Oct 2017
diff --git a/boost/outcome/policy/result_exception_ptr_rethrow.hpp b/boost/outcome/policy/result_exception_ptr_rethrow.hpp
index 37991ae783..d78b9b5d96 100644
--- a/boost/outcome/policy/result_exception_ptr_rethrow.hpp
+++ b/boost/outcome/policy/result_exception_ptr_rethrow.hpp
@@ -1,5 +1,5 @@
/* Policies for result and outcome
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
File Created: Oct 2017
diff --git a/boost/outcome/policy/terminate.hpp b/boost/outcome/policy/terminate.hpp
index 41a9894a9f..5903522929 100644
--- a/boost/outcome/policy/terminate.hpp
+++ b/boost/outcome/policy/terminate.hpp
@@ -1,5 +1,5 @@
/* Policies for result and outcome
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
File Created: Oct 2017
diff --git a/boost/outcome/policy/throw_bad_result_access.hpp b/boost/outcome/policy/throw_bad_result_access.hpp
index 4b13da47b2..bb6ffc289a 100644
--- a/boost/outcome/policy/throw_bad_result_access.hpp
+++ b/boost/outcome/policy/throw_bad_result_access.hpp
@@ -1,5 +1,5 @@
/* Policies for result and outcome
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (13 commits)
File Created: Oct 2017
diff --git a/boost/outcome/result.hpp b/boost/outcome/result.hpp
index 46e2d6da64..f14ffe5e63 100644
--- a/boost/outcome/result.hpp
+++ b/boost/outcome/result.hpp
@@ -1,5 +1,5 @@
/* A very simple result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
File Created: June 2017
diff --git a/boost/outcome/revision.hpp b/boost/outcome/revision.hpp
deleted file mode 100644
index 96c9a67f56..0000000000
--- a/boost/outcome/revision.hpp
+++ /dev/null
@@ -1,4 +0,0 @@
-// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
-#define BOOST_OUTCOME_PREVIOUS_COMMIT_REF b93403b9a55355b8f6783320c8d2db2c14b3517d
-#define BOOST_OUTCOME_PREVIOUS_COMMIT_DATE "2019-02-28 22:02:20 +00:00"
-#define BOOST_OUTCOME_PREVIOUS_COMMIT_UNIQUE b93403b9
diff --git a/boost/outcome/std_outcome.hpp b/boost/outcome/std_outcome.hpp
index 735615b849..58d85e1570 100644
--- a/boost/outcome/std_outcome.hpp
+++ b/boost/outcome/std_outcome.hpp
@@ -1,5 +1,5 @@
/* A less simple result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
File Created: June 2017
@@ -34,10 +34,13 @@ DEALINGS IN THE SOFTWARE.
#include "basic_outcome.hpp"
#include "std_result.hpp"
+#ifndef STD_BASIC_OUTCOME_FAILURE_EXCEPTION_FROM_ERROR
+#define STD_BASIC_OUTCOME_FAILURE_EXCEPTION_FROM_ERROR
namespace std // NOLINT
{
inline exception_ptr basic_outcome_failure_exception_from_error(const error_code &ec) { return make_exception_ptr(system_error(ec)); }
} // namespace std
+#endif
BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
diff --git a/boost/outcome/std_result.hpp b/boost/outcome/std_result.hpp
index 3a30078765..19467296fa 100644
--- a/boost/outcome/std_result.hpp
+++ b/boost/outcome/std_result.hpp
@@ -1,5 +1,5 @@
/* A very simple result type
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (8 commits)
File Created: June 2017
diff --git a/boost/outcome/success_failure.hpp b/boost/outcome/success_failure.hpp
index c697769f35..06ca0be2ab 100644
--- a/boost/outcome/success_failure.hpp
+++ b/boost/outcome/success_failure.hpp
@@ -1,5 +1,5 @@
/* Type sugar for success and failure
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (25 commits)
File Created: July 2017
diff --git a/boost/outcome/trait.hpp b/boost/outcome/trait.hpp
index 3279dcbf0b..7690919bab 100644
--- a/boost/outcome/trait.hpp
+++ b/boost/outcome/trait.hpp
@@ -1,5 +1,5 @@
/* Traits for Outcome
-(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (8 commits)
File Created: March 2018
@@ -119,9 +119,9 @@ type definition is_exception_ptr_available. Potential doc page: NOT FOUND
*/
template <class T> struct is_exception_ptr_available
{
- static constexpr bool value = detail::_is_exception_ptr_available<std::decay<T>>::value;
+ static constexpr bool value = detail::_is_exception_ptr_available<std::decay_t<T>>::value;
};
- template <class T> constexpr bool is_exception_ptr_available_v = detail::_is_exception_ptr_available<std::decay<T>>::value;
+ template <class T> constexpr bool is_exception_ptr_available_v = detail::_is_exception_ptr_available<std::decay_t<T>>::value;
} // namespace trait
diff --git a/boost/outcome/try.hpp b/boost/outcome/try.hpp
index 5dbf6333cb..91ebadc190 100644
--- a/boost/outcome/try.hpp
+++ b/boost/outcome/try.hpp
@@ -1,5 +1,5 @@
/* Try operation macros
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
File Created: July 2017
@@ -33,49 +33,106 @@ DEALINGS IN THE SOFTWARE.
#include "success_failure.hpp"
-namespace std // NOLINT
+BOOST_OUTCOME_V2_NAMESPACE_BEGIN
+
+namespace detail
{
- namespace experimental
+ struct has_value_overload
+ {
+ };
+ struct as_failure_overload
+ {
+ };
+ struct assume_error_overload
{
- template <class T, class E> class expected;
- template <class E> class unexpected;
- } // namespace experimental
-} // namespace std
+ };
+ struct error_overload
+ {
+ };
+ struct assume_value_overload
+ {
+ };
+ struct value_overload
+ {
+ };
+ BOOST_OUTCOME_TEMPLATE(class T, class R = decltype(std::declval<T>().as_failure()))
+ BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(BOOST_OUTCOME_V2_NAMESPACE::is_failure_type<R>))
+ constexpr inline bool has_as_failure(int/*unused */) { return true; }
+ template<class T> constexpr inline bool has_as_failure(...) { return false; }
+ BOOST_OUTCOME_TEMPLATE(class T)
+ BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().assume_error()))
+ constexpr inline bool has_assume_error(int/*unused */) { return true; }
+ template<class T> constexpr inline bool has_assume_error(...) { return false; }
+ BOOST_OUTCOME_TEMPLATE(class T)
+ BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().error()))
+ constexpr inline bool has_error(int/*unused */) { return true; }
+ template<class T> constexpr inline bool has_error(...) { return false; }
+ BOOST_OUTCOME_TEMPLATE(class T)
+ BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().assume_value()))
+ constexpr inline bool has_assume_value(int/*unused */) { return true; }
+ template<class T> constexpr inline bool has_assume_value(...) { return false; }
+ BOOST_OUTCOME_TEMPLATE(class T)
+ BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().value()))
+ constexpr inline bool has_value(int/*unused */) { return true; }
+ template<class T> constexpr inline bool has_value(...) { return false; }
+} // namespace detail
-BOOST_OUTCOME_V2_NAMESPACE_BEGIN
+/*! AWAITING HUGO JSON CONVERSION TOOL
+SIGNATURE NOT RECOGNISED
+*/
+BOOST_OUTCOME_TEMPLATE(class T)
+BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().has_value()))
+constexpr inline bool try_operation_has_value(T &&v, detail::has_value_overload = {})
+{
+ return v.has_value();
+}
-/*! AWAITING HUGO JSON CONVERSION TOOL
+/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
BOOST_OUTCOME_TEMPLATE(class T)
-BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().as_failure()))
-inline decltype(auto) try_operation_return_as(T &&v)
+BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::has_as_failure<T>(5)))
+constexpr inline decltype(auto) try_operation_return_as(T &&v, detail::as_failure_overload = {})
{
return static_cast<T &&>(v).as_failure();
}
-/*! AWAITING HUGO JSON CONVERSION TOOL
+/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
-template <class T, class E> inline auto try_operation_return_as(const std::experimental::expected<T, E> &v)
+BOOST_OUTCOME_TEMPLATE(class T)
+BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!detail::has_as_failure<T>(5) && detail::has_assume_error<T>(5)))
+constexpr inline decltype(auto) try_operation_return_as(T &&v, detail::assume_error_overload = {})
{
- return std::experimental::unexpected<E>(v.error());
+ return failure(static_cast<T &&>(v).assume_error());
}
-/*! AWAITING HUGO JSON CONVERSION TOOL
+/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
-template <class T, class E> inline auto try_operation_return_as(std::experimental::expected<T, E> &&v)
+BOOST_OUTCOME_TEMPLATE(class T)
+BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!detail::has_as_failure<T>(5) && !detail::has_assume_error<T>(5) && detail::has_error<T>(5)))
+constexpr inline decltype(auto) try_operation_return_as(T &&v, detail::error_overload = {})
{
- return std::experimental::unexpected<E>(static_cast<std::experimental::expected<T, E> &&>(v).error());
+ return failure(static_cast<T &&>(v).error());
}
-namespace detail
+/*! AWAITING HUGO JSON CONVERSION TOOL
+SIGNATURE NOT RECOGNISED
+*/
+BOOST_OUTCOME_TEMPLATE(class T)
+BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::has_assume_value<T>(5)))
+constexpr inline decltype(auto) try_operation_extract_value(T &&v, detail::assume_value_overload = {})
{
- BOOST_OUTCOME_TEMPLATE(class T)
- BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<T>().assume_value()))
- inline decltype(auto) try_extract_value(T &&v) { return static_cast<T &&>(v).assume_value(); }
-
- template <class T, class... Args> inline decltype(auto) try_extract_value(T &&v, Args &&... /*unused*/) { return static_cast<T &&>(v).value(); }
-} // namespace detail
+ return static_cast<T &&>(v).assume_value();
+}
+/*! AWAITING HUGO JSON CONVERSION TOOL
+SIGNATURE NOT RECOGNISED
+*/
+BOOST_OUTCOME_TEMPLATE(class T)
+BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!detail::has_assume_value<T>(5) && detail::has_value<T>(5)))
+constexpr inline decltype(auto) try_operation_extract_value(T &&v, detail::value_overload = {})
+{
+ return static_cast<T &&>(v).value();
+}
BOOST_OUTCOME_V2_NAMESPACE_END
@@ -99,37 +156,36 @@ BOOST_OUTCOME_V2_NAMESPACE_END
#define BOOST_OUTCOME_TRYV2(unique, ...) \
auto && (unique) = (__VA_ARGS__); \
- if(!(unique).has_value()) \
+ if(!BOOST_OUTCOME_V2_NAMESPACE::try_operation_has_value(unique)) \
return BOOST_OUTCOME_V2_NAMESPACE::try_operation_return_as(static_cast<decltype(unique) &&>(unique))
#define BOOST_OUTCOME_TRY2(unique, v, ...) \
BOOST_OUTCOME_TRYV2(unique, __VA_ARGS__); \
- auto && (v) = BOOST_OUTCOME_V2_NAMESPACE::detail::try_extract_value(static_cast<decltype(unique) &&>(unique))
+ auto && (v) = BOOST_OUTCOME_V2_NAMESPACE::try_operation_extract_value(static_cast<decltype(unique) &&>(unique))
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
-/*! AWAITING HUGO JSON CONVERSION TOOL
+/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define BOOST_OUTCOME_TRYV(...) BOOST_OUTCOME_TRYV2(BOOST_OUTCOME_TRY_UNIQUE_NAME, __VA_ARGS__)
#if defined(__GNUC__) || defined(__clang__)
-/*! AWAITING HUGO JSON CONVERSION TOOL
+/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define BOOST_OUTCOME_TRYX(...) \
({ \
auto &&res = (__VA_ARGS__); \
- if(!res.has_value()) \
+ if(!BOOST_OUTCOME_V2_NAMESPACE::try_operation_has_value(res)) \
return BOOST_OUTCOME_V2_NAMESPACE::try_operation_return_as(static_cast<decltype(res) &&>(res)); \
- BOOST_OUTCOME_V2_NAMESPACE::detail::try_extract_value(static_cast<decltype(res) &&>(res)); \
- \
-})
+ BOOST_OUTCOME_V2_NAMESPACE::try_operation_extract_value(static_cast<decltype(res) &&>(res)); \
+ })
#endif
-/*! AWAITING HUGO JSON CONVERSION TOOL
+/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define BOOST_OUTCOME_TRYA(v, ...) BOOST_OUTCOME_TRY2(BOOST_OUTCOME_TRY_UNIQUE_NAME, v, __VA_ARGS__)
@@ -142,7 +198,7 @@ SIGNATURE NOT RECOGNISED
#define BOOST_OUTCOME_TRY_INVOKE_TRY3(a, b, c) BOOST_OUTCOME_TRYA(a, b, c)
#define BOOST_OUTCOME_TRY_INVOKE_TRY2(a, b) BOOST_OUTCOME_TRYA(a, b)
#define BOOST_OUTCOME_TRY_INVOKE_TRY1(a) BOOST_OUTCOME_TRYV(a)
-/*! AWAITING HUGO JSON CONVERSION TOOL
+/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define BOOST_OUTCOME_TRY(...) BOOST_OUTCOME_TRY_CALL_OVERLOAD(BOOST_OUTCOME_TRY_INVOKE_TRY, __VA_ARGS__)
diff --git a/boost/outcome/utils.hpp b/boost/outcome/utils.hpp
index 2a7da2ef1a..012d0a78f5 100644
--- a/boost/outcome/utils.hpp
+++ b/boost/outcome/utils.hpp
@@ -1,5 +1,5 @@
/* Tries to convert an exception ptr into its equivalent error code
-(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (59 commits)
+(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
File Created: July 2017
diff --git a/boost/outcome/version.hpp b/boost/outcome/version.hpp
deleted file mode 100644
index f42cf39383..0000000000
--- a/boost/outcome/version.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-/*! AWAITING HUGO JSON CONVERSION TOOL */
-#define BOOST_OUTCOME_VERSION_MAJOR 2
-/*! AWAITING HUGO JSON CONVERSION TOOL */
-#define BOOST_OUTCOME_VERSION_MINOR 0
-/*! AWAITING HUGO JSON CONVERSION TOOL */
-#define BOOST_OUTCOME_VERSION_PATCH 0
-/*! AWAITING HUGO JSON CONVERSION TOOL */
-#define BOOST_OUTCOME_VERSION_REVISION 0 // Revision version for cmake and DLL version stamping
-
-/*! AWAITING HUGO JSON CONVERSION TOOL */
-#ifndef BOOST_OUTCOME_DISABLE_ABI_PERMUTATION
-#define BOOST_OUTCOME_UNSTABLE_VERSION
-#endif
diff --git a/boost/parameter.hpp b/boost/parameter.hpp
index 3cc70cb109..b6e666cbf4 100644
--- a/boost/parameter.hpp
+++ b/boost/parameter.hpp
@@ -1,6 +1,6 @@
-// Copyright David Abrahams, Daniel Wallin 2005. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
+// Copyright David Abrahams, Daniel Wallin 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See www.boost.org/libs/parameter for documentation.
@@ -9,13 +9,22 @@
#define BOOST_PARAMETER_050401_HPP
#include <boost/parameter/parameters.hpp>
+#include <boost/parameter/are_tagged_arguments.hpp>
+#include <boost/parameter/is_argument_pack.hpp>
+#include <boost/parameter/required.hpp>
+#include <boost/parameter/optional.hpp>
+#include <boost/parameter/deduced.hpp>
+#include <boost/parameter/template_keyword.hpp>
#include <boost/parameter/keyword.hpp>
+#include <boost/parameter/nested_keyword.hpp>
#include <boost/parameter/binding.hpp>
#include <boost/parameter/value_type.hpp>
#include <boost/parameter/macros.hpp>
#include <boost/parameter/match.hpp>
#include <boost/parameter/name.hpp>
+#include <boost/parameter/compose.hpp>
#include <boost/parameter/preprocessor.hpp>
+#include <boost/parameter/preprocessor_no_spec.hpp>
-#endif // BOOST_PARAMETER_050401_HPP
+#endif // include guard
diff --git a/boost/parameter/are_tagged_arguments.hpp b/boost/parameter/are_tagged_arguments.hpp
new file mode 100644
index 0000000000..84157c4118
--- /dev/null
+++ b/boost/parameter/are_tagged_arguments.hpp
@@ -0,0 +1,125 @@
+// Copyright Cromwell D. Enage 2018.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_ARE_TAGGED_ARGUMENTS_HPP
+#define BOOST_PARAMETER_ARE_TAGGED_ARGUMENTS_HPP
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+namespace boost { namespace parameter {
+
+ template <typename TaggedArg0, typename ...TaggedArgs>
+ struct are_tagged_arguments;
+}} // namespace boost::parameter
+
+#include <boost/parameter/aux_/is_tagged_argument.hpp>
+
+namespace boost { namespace parameter {
+
+ template <typename TaggedArg0>
+ struct are_tagged_arguments<TaggedArg0>
+ : ::boost::parameter::aux::is_tagged_argument<TaggedArg0>
+ {
+ };
+}} // namespace boost::parameter
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+
+namespace boost { namespace parameter {
+
+ template <typename TaggedArg0, typename ...TaggedArgs>
+ struct are_tagged_arguments
+ : ::boost::mpl::if_<
+ ::boost::parameter::aux::is_tagged_argument<TaggedArg0>
+ , ::boost::parameter::are_tagged_arguments<TaggedArgs...>
+ , ::boost::mpl::false_
+ >::type
+ {
+ };
+}} // namespace boost::parameter
+
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+#define BOOST_PARAMETER_ARE_TAGGED_ARGUMENTS_END_Z(z, n, false_t) , false_t>
+/**/
+
+#include <boost/parameter/aux_/is_tagged_argument.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+#define BOOST_PARAMETER_ARE_TAGGED_ARGUMENTS_BEGIN_Z(z, n, prefix) \
+ ::boost::mpl::eval_if< \
+ ::boost::parameter::aux::is_tagged_argument<BOOST_PP_CAT(prefix, n)>,
+/**/
+
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/facilities/intercept.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+
+#define BOOST_PARAMETER_ARE_TAGGED_ARGUMENTS_OVERLOADS_Z(z, n, prefix) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename prefix)> \
+ struct are_tagged_arguments< \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, prefix) \
+ BOOST_PP_ENUM_TRAILING_PARAMS_Z( \
+ z \
+ , BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, n) \
+ , ::boost::parameter::void_ BOOST_PP_INTERCEPT \
+ ) \
+ > : BOOST_PP_CAT(BOOST_PP_REPEAT_, z)( \
+ n \
+ , BOOST_PARAMETER_ARE_TAGGED_ARGUMENTS_BEGIN_Z \
+ , prefix \
+ ) \
+ ::boost::mpl::true_ \
+ BOOST_PP_CAT(BOOST_PP_REPEAT_, z)( \
+ n \
+ , BOOST_PARAMETER_ARE_TAGGED_ARGUMENTS_END_Z \
+ , ::boost::mpl::false_ \
+ )::type \
+ { \
+ };
+/**/
+
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+
+namespace boost { namespace parameter {
+
+ template <
+ BOOST_PP_ENUM_BINARY_PARAMS(
+ BOOST_PP_INC(BOOST_PARAMETER_COMPOSE_MAX_ARITY)
+ , typename TaggedArg
+ , = ::boost::parameter::void_ BOOST_PP_INTERCEPT
+ )
+ >
+ struct are_tagged_arguments;
+}} // namespace boost::parameter
+
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+namespace boost { namespace parameter {
+
+ BOOST_PP_REPEAT_FROM_TO(
+ 1
+ , BOOST_PP_INC(BOOST_PARAMETER_COMPOSE_MAX_ARITY)
+ , BOOST_PARAMETER_ARE_TAGGED_ARGUMENTS_OVERLOADS_Z
+ , TaggedArg
+ )
+}} // namespace boost::parameter
+
+#undef BOOST_PARAMETER_ARE_TAGGED_ARGUMENTS_OVERLOADS_Z
+#undef BOOST_PARAMETER_ARE_TAGGED_ARGUMENTS_BEGIN_Z
+#undef BOOST_PARAMETER_ARE_TAGGED_ARGUMENTS_END_Z
+
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+#endif // include guard
+
diff --git a/boost/parameter/aux_/always_true_predicate.hpp b/boost/parameter/aux_/always_true_predicate.hpp
new file mode 100644
index 0000000000..ca1ece42f6
--- /dev/null
+++ b/boost/parameter/aux_/always_true_predicate.hpp
@@ -0,0 +1,42 @@
+// Copyright Cromwell D. Enage 2019.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_ALWAYS_TRUE_PREDICATE_HPP
+#define BOOST_PARAMETER_AUX_ALWAYS_TRUE_PREDICATE_HPP
+
+#include <boost/parameter/config.hpp>
+#include <boost/mpl/bool.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#endif
+#else
+#include <boost/mpl/always.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+ struct always_true_predicate
+ {
+ template <typename ...>
+ struct apply
+ {
+ typedef ::boost::mpl::true_ type;
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename ...>
+ using fn = ::boost::mp11::mp_true;
+#endif
+ };
+#else
+ typedef ::boost::mpl::always< ::boost::mpl::true_> always_true_predicate;
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/arg_list.hpp b/boost/parameter/aux_/arg_list.hpp
index 721ce04004..ffe1bac184 100644
--- a/boost/parameter/aux_/arg_list.hpp
+++ b/boost/parameter/aux_/arg_list.hpp
@@ -1,437 +1,1331 @@
-// Copyright Daniel Wallin, David Abrahams 2005. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Copyright Cromwell D. Enage 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 ARG_LIST_050329_HPP
#define ARG_LIST_050329_HPP
+namespace boost { namespace parameter { namespace aux {
+
+ //
+ // Structures used to build the tuple of actual arguments. The tuple is a
+ // nested cons-style list of arg_list specializations terminated by an
+ // empty_arg_list.
+ //
+ // Each specialization of arg_list is derived from its successor in the
+ // list type. This feature is used along with using declarations to build
+ // member function overload sets that can match against keywords.
+ //
+
+ // MPL sequence support
+ struct arg_list_tag;
+
+ template <typename T>
+ struct get_reference
+ {
+ typedef typename T::reference type;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+namespace boost { namespace parameter { namespace aux {
+
+ struct value_type_is_void
+ {
+ };
+
+ struct value_type_is_not_void
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif
+
#include <boost/parameter/aux_/void.hpp>
+#include <boost/parameter/aux_/yesno.hpp>
#include <boost/parameter/aux_/result_of0.hpp>
#include <boost/parameter/aux_/default.hpp>
-#include <boost/parameter/aux_/parameter_requirements.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#include <utility>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Terminates arg_list<> and represents an empty list. Since this is just
+ // the terminating case, you might want to look at arg_list first to get a
+ // feel for what's really happening here.
+ struct empty_arg_list
+ {
+ struct tagged_arg
+ {
+ typedef ::boost::parameter::void_ value_type;
+ };
+
+ // Variadic constructor also serves as default constructor.
+ template <typename ...Args>
+ inline BOOST_CONSTEXPR empty_arg_list(Args&&...)
+ {
+ }
+
+ // A metafunction class that, given a keyword and a default type,
+ // returns the appropriate result type for a keyword lookup given
+ // that default.
+ struct binding
+ {
+ template <typename KW, typename Default, typename Reference>
+ struct apply
+ {
+ typedef Default type;
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename KW, typename Default, typename Reference>
+ using fn = Default;
+#endif
+ };
+
+ // Terminator for has_key, indicating that the keyword is unique.
+ template <typename KW>
+ static ::boost::parameter::aux::no_tag has_key(KW*);
+
+ // If either of these operators are called, it means there is no
+ // argument in the list that matches the supplied keyword. Just
+ // return the default value.
+ template <typename K, typename Default>
+ inline BOOST_CONSTEXPR Default&
+ operator[](::boost::parameter::aux::default_<K,Default> x) const
+ {
+ return x.value;
+ }
+
+ template <typename K, typename Default>
+ inline BOOST_CONSTEXPR Default&&
+ operator[](::boost::parameter::aux::default_r_<K,Default> x) const
+ {
+ return ::std::forward<Default>(x.value);
+ }
+
+ // If this operator is called, it means there is no argument in the
+ // list that matches the supplied keyword. Just evaluate and return
+ // the default value.
+ template <typename K, typename F>
+ inline BOOST_CONSTEXPR
+ typename ::boost::parameter::aux::result_of0<F>::type
+ operator[](BOOST_PARAMETER_lazy_default_fallback<K,F> x) const
+ {
+ return x.compute_default();
+ }
+
+ // No argument corresponding to ParameterRequirements::key_type
+ // was found if we match this overload, so unless that parameter
+ // has a default, we indicate that the actual arguments don't
+ // match the function's requirements.
+ template <typename ParameterRequirements, typename ArgPack>
+ static typename ParameterRequirements::has_default
+ satisfies(ParameterRequirements*, ArgPack*);
+
+ // MPL sequence support
+ typedef ::boost::parameter::aux::empty_arg_list type; // convenience
+ // For dispatching to sequence intrinsics
+ typedef ::boost::parameter::aux::arg_list_tag tag;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
#include <boost/parameter/aux_/yesno.hpp>
#include <boost/parameter/aux_/is_maybe.hpp>
-#include <boost/parameter/config.hpp>
-
-#include <boost/mpl/apply.hpp>
+#include <boost/parameter/aux_/tagged_argument_fwd.hpp>
+#include <boost/parameter/aux_/parameter_requirements.hpp>
+#include <boost/parameter/aux_/augment_predicate.hpp>
+#include <boost/parameter/keyword_fwd.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/apply_wrap.hpp>
#include <boost/mpl/assert.hpp>
-#include <boost/mpl/begin.hpp>
-#include <boost/mpl/end.hpp>
-#include <boost/mpl/iterator_tags.hpp>
-
-#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/is_same.hpp>
+#include <boost/core/enable_if.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // A tuple of tagged arguments, terminated with empty_arg_list. Every
+ // TaggedArg is an instance of tagged_argument<> or
+ // tagged_argument_rref<>.
+ template <
+ typename TaggedArg
+ , typename Next = ::boost::parameter::aux::empty_arg_list
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ , typename EmitsErrors = ::boost::mp11::mp_true
+#else
+ , typename EmitsErrors = ::boost::mpl::true_
+#endif
+ >
+ class arg_list : public Next
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using _holds_maybe = typename ::boost::parameter::aux
+ ::is_maybe<typename TaggedArg::value_type>::type;
+#else
+ typedef typename ::boost::parameter::aux
+ ::is_maybe<typename TaggedArg::value_type>::type _holds_maybe;
+#endif
+
+ TaggedArg arg; // Stores the argument
+
+ public:
+ typedef TaggedArg tagged_arg;
+ typedef ::boost::parameter::aux::arg_list<TaggedArg,Next> self;
+ typedef typename TaggedArg::key_type key_type;
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using reference = typename ::boost::mp11::mp_if<
+ _holds_maybe
+ , ::boost::parameter::aux
+ ::get_reference<typename TaggedArg::value_type>
+ , ::boost::parameter::aux::get_reference<TaggedArg>
+ >::type;
+
+ using value_type = ::boost::mp11
+ ::mp_if<_holds_maybe,reference,typename TaggedArg::value_type>;
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typedef typename ::boost::mpl::eval_if<
+ _holds_maybe
+ , ::boost::parameter::aux
+ ::get_reference<typename TaggedArg::value_type>
+ , ::boost::parameter::aux::get_reference<TaggedArg>
+ >::type reference;
+
+ typedef typename ::boost::mpl::if_<
+ _holds_maybe
+ , reference
+ , typename TaggedArg::value_type
+ >::type value_type;
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+ // Create a new list by prepending arg to a copy of tail. Used when
+ // incrementally building this structure with the comma operator.
+ inline BOOST_CONSTEXPR arg_list(
+ TaggedArg const& head
+ , Next const& tail
+ ) : Next(tail), arg(head)
+ {
+ }
+
+ // Store the arguments in successive nodes of this list.
+ // Use tag dispatching to determine whether to forward all arguments
+ // to the Next constructor, or store the first argument and forward
+ // the rest. -- Cromwell D. Enage
+ template <typename A0>
+ inline BOOST_CONSTEXPR arg_list(
+ ::boost::parameter::aux::value_type_is_not_void
+ , A0&& a0
+ ) : Next(
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::std::is_same<
+#else
+ typename ::boost::mpl::if_<
+ ::boost::is_same<
+#endif
+ typename Next::tagged_arg::value_type
+ , ::boost::parameter::void_
+ >
+ , ::boost::parameter::aux::value_type_is_void
+ , ::boost::parameter::aux::value_type_is_not_void
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >()
+#else
+ >::type()
+#endif
+ )
+ , arg(::std::forward<A0>(a0))
+ {
+ }
+
+ template <typename ...Args>
+ inline BOOST_CONSTEXPR arg_list(
+ ::boost::parameter::aux::value_type_is_void
+ , Args&&... args
+ ) : Next(
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::std::is_same<
+#else
+ typename ::boost::mpl::if_<
+ ::boost::is_same<
+#endif
+ typename Next::tagged_arg::value_type
+ , ::boost::parameter::void_
+ >
+ , ::boost::parameter::aux::value_type_is_void
+ , ::boost::parameter::aux::value_type_is_not_void
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >()
+#else
+ >::type()
+#endif
+ , ::std::forward<Args>(args)...
+ )
+ , arg(::boost::parameter::aux::void_reference())
+ {
+ }
+
+ template <typename A0, typename A1, typename ...Args>
+ inline BOOST_CONSTEXPR arg_list(
+ ::boost::parameter::aux::value_type_is_not_void
+ , A0&& a0
+ , A1&& a1
+ , Args&&... args
+ ) : Next(
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::std::is_same<
+#else
+ typename ::boost::mpl::if_<
+ ::boost::is_same<
+#endif
+ typename Next::tagged_arg::value_type
+ , ::boost::parameter::void_
+ >
+ , ::boost::parameter::aux::value_type_is_void
+ , ::boost::parameter::aux::value_type_is_not_void
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >()
+#else
+ >::type()
+#endif
+ , ::std::forward<A1>(a1)
+ , ::std::forward<Args>(args)...
+ )
+ , arg(::std::forward<A0>(a0))
+ {
+ }
+
+ // A metafunction class that, given a keyword and a default type,
+ // returns the appropriate result type for a keyword lookup given
+ // that default.
+ struct binding
+ {
+ typedef typename Next::binding next_binding;
+
+ template <typename KW, typename Default, typename Reference>
+ struct apply
+ {
+ typedef typename ::boost::mpl::eval_if<
+ ::boost::is_same<KW,key_type>
+ , ::boost::mpl::if_<Reference,reference,value_type>
+ , ::boost::mpl
+ ::apply_wrap3<next_binding,KW,Default,Reference>
+ >::type type;
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename KW, typename Default, typename Reference>
+ using fn = ::boost::mp11::mp_if<
+ ::std::is_same<KW,key_type>
+ , ::boost::mp11::mp_if<Reference,reference,value_type>
+ , ::boost::mp11::mp_apply_q<
+ next_binding
+ , ::boost::mp11::mp_list<KW,Default,Reference>
+ >
+ >;
+#endif
+ };
+
+ // Overload for key_type, so the assert below will fire
+ // if the same keyword is used again.
+ static ::boost::parameter::aux::yes_tag has_key(key_type*);
+ using Next::has_key;
+
+ private:
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using _has_unique_key = ::boost::mp11::mp_bool<
+#else
+ typedef ::boost::mpl::bool_<
+#endif
+ sizeof(
+ Next::has_key(
+ static_cast<key_type*>(BOOST_PARAMETER_AUX_PP_NULLPTR)
+ )
+ ) == sizeof(::boost::parameter::aux::no_tag)
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >;
+#else
+ > _has_unique_key;
+#endif
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ static_assert(
+ !(EmitsErrors::value) || (_has_unique_key::value)
+ , "duplicate keyword"
+ );
+#else
+ BOOST_MPL_ASSERT_MSG(
+ !(EmitsErrors::value) || (_has_unique_key::value)
+ , duplicate_keyword
+ , (key_type)
+ );
+#endif
+
+ //
+ // Begin implementation of indexing operators
+ // for looking up specific arguments by name.
+ //
+
+ // Helpers that handle the case when TaggedArg is empty<T>.
+ template <typename D>
+ inline BOOST_CONSTEXPR reference
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ get_default(D const&, ::boost::mp11::mp_false) const
+#else
+ get_default(D const&, ::boost::mpl::false_) const
+#endif
+ {
+ return this->arg.get_value();
+ }
+
+ template <typename D>
+ inline BOOST_CONSTEXPR reference
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ get_default(D const& d, ::boost::mp11::mp_true) const
+#else
+ get_default(D const& d, ::boost::mpl::true_) const
+#endif
+ {
+ return (
+ this->arg.get_value()
+ ? this->arg.get_value().get()
+ : this->arg.get_value().construct(d.value)
+ );
+ }
+
+ public:
+ inline BOOST_CONSTEXPR reference
+ operator[](::boost::parameter::keyword<key_type> const&) const
+ {
+#if !defined(BOOST_NO_CXX14_CONSTEXPR)
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ static_assert(!_holds_maybe::value, "must not hold maybe");
+#elif !( \
+ BOOST_WORKAROUND(BOOST_GCC, >= 40700) && \
+ BOOST_WORKAROUND(BOOST_GCC, < 40900) \
+ ) && !BOOST_WORKAROUND(BOOST_GCC, >= 50000) && \
+ !BOOST_WORKAROUND(BOOST_MSVC, < 1910)
+ BOOST_MPL_ASSERT_NOT((_holds_maybe));
+#endif
+#endif
+ return this->arg.get_value();
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ ::boost::parameter::aux::default_<key_type,Default> const& d
+ ) const
+ {
+ return this->get_default(d, _holds_maybe());
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ ::boost::parameter::aux::default_r_<key_type,Default> const& d
+ ) const
+ {
+ return this->get_default(d, _holds_maybe());
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ BOOST_PARAMETER_lazy_default_fallback<key_type,Default> const&
+ ) const
+ {
+#if !defined(BOOST_NO_CXX14_CONSTEXPR)
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ static_assert(!_holds_maybe::value, "must not hold maybe");
+#elif !( \
+ BOOST_WORKAROUND(BOOST_GCC, >= 40700) && \
+ BOOST_WORKAROUND(BOOST_GCC, < 40900) \
+ ) && !BOOST_WORKAROUND(BOOST_GCC, >= 50000) && \
+ !BOOST_WORKAROUND(BOOST_MSVC, < 1910)
+ BOOST_MPL_ASSERT_NOT((_holds_maybe));
+#endif
+#endif
+ return this->arg.get_value();
+ }
+
+ // Builds an overload set including operator[]s defined
+ // in base classes.
+ using Next::operator[];
+
+ //
+ // End of indexing support
+ //
+
+ // For parameter_requirements matching this node's key_type, return
+ // a bool constant wrapper indicating whether the requirements are
+ // satisfied by TaggedArg. Used only for compile-time computation
+ // and never really called, so a declaration is enough.
+ template <typename HasDefault, typename Predicate, typename ArgPack>
+ static typename ::boost::lazy_enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ EmitsErrors
+ , ::boost::mp11::mp_true
+ , _has_unique_key
+ >
+ , ::boost::parameter::aux::augment_predicate_mp11<
+#else
+ typename ::boost::mpl::if_<
+ EmitsErrors
+ , ::boost::mpl::true_
+ , _has_unique_key
+ >::type
+ , ::boost::parameter::aux::augment_predicate<
+#endif
+ Predicate
+ , reference
+ , key_type
+ , value_type
+ , ArgPack
+ >
+ >::type
+ satisfies(
+ ::boost::parameter::aux::parameter_requirements<
+ key_type
+ , Predicate
+ , HasDefault
+ >*
+ , ArgPack*
+ );
+
+ // Builds an overload set including satisfies functions defined
+ // in base classes.
+ using Next::satisfies;
+
+ // Comma operator to compose argument list without using parameters<>.
+ // Useful for argument lists with undetermined length.
+ template <typename KW, typename T2>
+ inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<KW,T2>
+ , self
+ >
+ operator,(
+ ::boost::parameter::aux::tagged_argument<KW,T2> const& x
+ ) const
+ {
+ return ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<KW,T2>
+ , self
+ >(x, *this);
+ }
+
+ template <typename KW, typename T2>
+ inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument_rref<KW,T2>
+ , self
+ >
+ operator,(
+ ::boost::parameter::aux::tagged_argument_rref<KW,T2> const& x
+ ) const
+ {
+ return ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument_rref<KW,T2>
+ , self
+ >(x, *this);
+ }
+
+ // MPL sequence support
+ typedef self type; // Convenience for users
+ typedef Next tail_type; // For the benefit of iterators
+ // For dispatching to sequence intrinsics
+ typedef ::boost::parameter::aux::arg_list_tag tag;
+ };
+}}} // namespace boost::parameter::aux
+
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>
-namespace boost { namespace parameter {
+namespace boost { namespace parameter { namespace aux {
-// Forward declaration for aux::arg_list, below.
-template<class T> struct keyword;
+ // Terminates arg_list<> and represents an empty list. Since this is just
+ // the terminating case, you might want to look at arg_list first to get a
+ // feel for what's really happening here.
+ struct empty_arg_list
+ {
+ inline BOOST_CONSTEXPR empty_arg_list()
+ {
+ }
+
+ // Constructor taking BOOST_PARAMETER_COMPOSE_MAX_ARITY empty_arg_list
+ // arguments; this makes initialization.
+ inline BOOST_CONSTEXPR empty_arg_list(
+ BOOST_PP_ENUM_PARAMS(
+ BOOST_PARAMETER_COMPOSE_MAX_ARITY
+ , ::boost::parameter::void_ BOOST_PP_INTERCEPT
+ )
+ )
+ {
+ }
-namespace aux {
+ // A metafunction class that, given a keyword and a default type,
+ // returns the appropriate result type for a keyword lookup given
+ // that default.
+ struct binding
+ {
+ template <typename KW, typename Default, typename Reference>
+ struct apply
+ {
+ typedef Default type;
+ };
+ };
-// Tag type passed to MPL lambda.
-struct lambda_tag;
+ // Terminator for has_key, indicating that the keyword is unique.
+ template <typename KW>
+ static ::boost::parameter::aux::no_tag has_key(KW*);
-//
-// Structures used to build the tuple of actual arguments. The
-// tuple is a nested cons-style list of arg_list specializations
-// terminated by an empty_arg_list.
-//
-// Each specialization of arg_list is derived from its successor in
-// the list type. This feature is used along with using
-// declarations to build member function overload sets that can
-// match against keywords.
-//
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ // The overload set technique doesn't work with these older compilers,
+ // so they need some explicit handholding.
-// MPL sequence support
-struct arg_list_tag;
-
-// Terminates arg_list<> and represents an empty list. Since this
-// is just the terminating case you might want to look at arg_list
-// first, to get a feel for what's really happening here.
-
-struct empty_arg_list
-{
- empty_arg_list() {}
-
- // Constructor taking BOOST_PARAMETER_MAX_ARITY empty_arg_list
- // arguments; this makes initialization
- empty_arg_list(
- BOOST_PP_ENUM_PARAMS(
- BOOST_PARAMETER_MAX_ARITY, void_ BOOST_PP_INTERCEPT
- ))
- {}
-
- // A metafunction class that, given a keyword and a default
- // type, returns the appropriate result type for a keyword
- // lookup given that default
- struct binding
- {
- template<class KW, class Default, class Reference>
- struct apply
+ // A metafunction class that, given a keyword, returns the type of the
+ // base sublist whose get() function can produce the value for that key.
+ struct key_owner
{
- typedef Default type;
+ template <typename KW>
+ struct apply
+ {
+ typedef ::boost::parameter::aux::empty_arg_list type;
+ };
};
+#endif // Borland workarounds needed
+
+ // If either of these operators are called, it means there is no
+ // argument in the list that matches the supplied keyword. Just
+ // return the default value.
+ template <typename K, typename Default>
+ inline BOOST_CONSTEXPR Default&
+ operator[](::boost::parameter::aux::default_<K,Default> x) const
+ {
+ return x.value;
+ }
+
+ // If this operator is called, it means there is no argument in the
+ // list that matches the supplied keyword. Just evaluate and return
+ // the default value.
+ template <typename K, typename F>
+ inline BOOST_CONSTEXPR
+ typename ::boost::parameter::aux::result_of0<F>::type
+ operator[](BOOST_PARAMETER_lazy_default_fallback<K,F> x) const
+ {
+ return x.compute_default();
+ }
+
+ // No argument corresponding to ParameterRequirements::key_type
+ // was found if we match this overload, so unless that parameter
+ // has a default, we indicate that the actual arguments don't
+ // match the function's requirements.
+ template <typename ParameterRequirements, typename ArgPack>
+ static typename ParameterRequirements::has_default
+ satisfies(ParameterRequirements*, ArgPack*);
+
+ // MPL sequence support
+ typedef ::boost::parameter::aux::empty_arg_list type; // convenience
+ // For dispatching to sequence intrinsics
+ typedef ::boost::parameter::aux::arg_list_tag tag;
};
+}}} // namespace boost::parameter::aux
- // Terminator for has_key, indicating that the keyword is unique
- template <class KW>
- static no_tag has_key(KW*);
+#include <boost/parameter/aux_/yesno.hpp>
+#include <boost/parameter/aux_/is_maybe.hpp>
+#include <boost/parameter/aux_/tagged_argument_fwd.hpp>
+#include <boost/parameter/aux_/parameter_requirements.hpp>
+#include <boost/parameter/aux_/augment_predicate.hpp>
+#include <boost/parameter/keyword_fwd.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+#include <boost/core/enable_if.hpp>
+#endif
+
+#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
+#endif
- // The overload set technique doesn't work with these older
- // compilers, so they need some explicit handholding.
+namespace boost { namespace parameter { namespace aux {
- // A metafunction class that, given a keyword, returns the type
- // of the base sublist whose get() function can produce the
- // value for that key
- struct key_owner
+ // A tuple of tagged arguments, terminated with empty_arg_list. Every
+ // TaggedArg is an instance of tagged_argument<>.
+ template <
+ typename TaggedArg
+ , typename Next = ::boost::parameter::aux::empty_arg_list
+ , typename EmitsErrors = ::boost::mpl::true_
+ >
+ class arg_list : public Next
{
- template<class KW>
- struct apply
+ typedef typename ::boost::parameter::aux
+ ::is_maybe<typename TaggedArg::value_type>::type _holds_maybe;
+
+ TaggedArg arg; // Stores the argument
+
+ public:
+ typedef TaggedArg tagged_arg;
+ typedef ::boost::parameter::aux::arg_list<TaggedArg,Next> self;
+ typedef typename TaggedArg::key_type key_type;
+
+ typedef typename ::boost::mpl::eval_if<
+ _holds_maybe
+ , ::boost::parameter::aux
+ ::get_reference<typename TaggedArg::value_type>
+ , ::boost::parameter::aux::get_reference<TaggedArg>
+ >::type reference;
+
+ typedef typename ::boost::mpl::if_<
+ _holds_maybe
+ , reference
+ , typename TaggedArg::value_type
+ >::type value_type;
+
+ // Create a new list by prepending arg to a copy of tail. Used when
+ // incrementally building this structure with the comma operator.
+ inline BOOST_CONSTEXPR arg_list(
+ TaggedArg const& head
+ , Next const& tail
+ ) : Next(tail), arg(head)
+ {
+ }
+
+ // Store the arguments in successive nodes of this list.
+ template <
+ // typename A0, typename A1, ...
+ BOOST_PP_ENUM_PARAMS(
+ BOOST_PARAMETER_COMPOSE_MAX_ARITY
+ , typename A
+ )
+ >
+ inline BOOST_CONSTEXPR arg_list(
+ // A0& a0, A1& a1, ...
+ BOOST_PP_ENUM_BINARY_PARAMS(
+ BOOST_PARAMETER_COMPOSE_MAX_ARITY
+ , A
+ , & a
+ )
+ ) : Next(
+ // a1, a2, ...
+ BOOST_PP_ENUM_SHIFTED_PARAMS(
+ BOOST_PARAMETER_COMPOSE_MAX_ARITY
+ , a
+ )
+ , ::boost::parameter::aux::void_reference()
+ )
+ , arg(a0)
+ {
+ }
+
+ // A metafunction class that, given a keyword and a default type,
+ // returns the appropriate result type for a keyword lookup given
+ // that default.
+ struct binding
+ {
+ typedef typename Next::binding next_binding;
+
+ template <typename KW, typename Default, typename Reference>
+ struct apply
+ {
+ typedef typename ::boost::mpl::eval_if<
+ ::boost::is_same<KW,key_type>
+ , ::boost::mpl::if_<Reference,reference,value_type>
+ , ::boost::mpl::apply_wrap3<
+ next_binding
+ , KW
+ , Default
+ , Reference
+ >
+ >::type type;
+ };
+ };
+
+#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ // Overload for key_type, so the assert below will fire
+ // if the same keyword is used again.
+ static ::boost::parameter::aux::yes_tag has_key(key_type*);
+ using Next::has_key;
+
+ private:
+#if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+ BOOST_MPL_ASSERT_MSG(
+ sizeof(
+ Next::has_key(
+ static_cast<key_type*>(BOOST_PARAMETER_AUX_PP_NULLPTR)
+ )
+ ) == sizeof(::boost::parameter::aux::no_tag)
+ , duplicate_keyword
+ , (key_type)
+ );
+#else
+ typedef ::boost::mpl::bool_<
+ sizeof(
+ Next::has_key(
+ static_cast<key_type*>(BOOST_PARAMETER_AUX_PP_NULLPTR)
+ )
+ ) == sizeof(::boost::parameter::aux::no_tag)
+ > _has_unique_key;
+
+ BOOST_MPL_ASSERT_MSG(
+ !(EmitsErrors::value) || (_has_unique_key::value)
+ , duplicate_keyword
+ , (key_type)
+ );
+#endif // SFINAE/MSVC workarounds needed
+#endif // Borland workarounds not needed
+
+ private:
+ //
+ // Begin implementation of indexing operators
+ // for looking up specific arguments by name.
+ //
+
+ // Helpers that handle the case when TaggedArg is empty<T>.
+ template <typename D>
+ inline BOOST_CONSTEXPR reference
+ get_default(D const&, ::boost::mpl::false_) const
+ {
+ return this->arg.get_value();
+ }
+
+ template <typename D>
+ inline BOOST_CONSTEXPR reference
+ get_default(D const& d, ::boost::mpl::true_) const
+ {
+ return (
+ this->arg.get_value()
+ ? this->arg.get_value().get()
+ : this->arg.get_value().construct(d.value)
+ );
+ }
+
+ public:
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ // These older compilers don't support the overload set creation
+ // idiom well, so we need to do all the return type calculation
+ // for the compiler and dispatch through an outer function template.
+
+ // A metafunction class that, given a keyword, returns the base
+ // sublist whose get() function can produce the value for that key.
+ struct key_owner
{
- typedef empty_arg_list type;
+ typedef typename Next::key_owner next_key_owner;
+
+ template <typename KW>
+ struct apply
+ {
+ typedef typename ::boost::mpl::eval_if<
+ ::boost::is_same<KW,key_type>
+ , ::boost::mpl::identity<
+ ::boost::parameter::aux::arg_list<TaggedArg,Next>
+ >
+ , ::boost::mpl::apply_wrap1<next_key_owner,KW>
+ >::type type;
+ };
};
+
+ // Outer indexing operators that dispatch to the right node's
+ // get() function.
+ template <typename KW>
+ inline BOOST_CONSTEXPR typename ::boost::mpl::apply_wrap3<
+ binding
+ , KW
+ , ::boost::parameter::void_
+ , ::boost::mpl::true_
+ >::type
+ operator[](::boost::parameter::keyword<KW> const& x) const
+ {
+ typename ::boost::mpl::apply_wrap1<key_owner,KW>::type const&
+ sublist = *this;
+ return sublist.get(x);
+ }
+
+ template <typename KW, typename Default>
+ inline BOOST_CONSTEXPR typename ::boost::mpl::apply_wrap3<
+ binding
+ , KW
+ , Default&
+ , ::boost::mpl::true_
+ >::type
+ operator[](
+ ::boost::parameter::aux::default_<KW,Default> const& x
+ ) const
+ {
+ typename ::boost::mpl::apply_wrap1<key_owner,KW>::type const&
+ sublist = *this;
+ return sublist.get(x);
+ }
+
+ template <typename KW, typename F>
+ inline BOOST_CONSTEXPR typename ::boost::mpl::apply_wrap3<
+ binding
+ , KW
+ , typename ::boost::parameter::aux::result_of0<F>::type
+ , ::boost::mpl::true_
+ >::type
+ operator[](
+ BOOST_PARAMETER_lazy_default_fallback<KW,F> const& x
+ ) const
+ {
+ typename ::boost::mpl::apply_wrap1<key_owner,KW>::type const&
+ sublist = *this;
+ return sublist.get(x);
+ }
+
+ // These just return the stored value; when empty_arg_list is reached,
+ // indicating no matching argument was passed, the default is
+ // returned, or if no default_ or lazy_default was passed, compilation
+ // fails.
+ inline BOOST_CONSTEXPR reference
+ get(::boost::parameter::keyword<key_type> const&) const
+ {
+ BOOST_MPL_ASSERT_NOT((_holds_maybe));
+ return this->arg.get_value();
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ get(
+ ::boost::parameter::aux::default_<key_type,Default> const& d
+ ) const
+ {
+ return this->get_default(d, _holds_maybe());
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ get(
+ BOOST_PARAMETER_lazy_default_fallback<key_type,Default> const&
+ ) const
+ {
+ return this->arg.get_value();
+ }
+#else // !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ inline BOOST_CONSTEXPR reference
+ operator[](::boost::parameter::keyword<key_type> const&) const
+ {
+ BOOST_MPL_ASSERT_NOT((_holds_maybe));
+ return this->arg.get_value();
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ ::boost::parameter::aux::default_<key_type,Default> const& d
+ ) const
+ {
+ return this->get_default(d, _holds_maybe());
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ BOOST_PARAMETER_lazy_default_fallback<key_type,Default> const&
+ ) const
+ {
+ BOOST_MPL_ASSERT_NOT((_holds_maybe));
+ return this->arg.get_value();
+ }
+
+ // Builds an overload set including operator[]s defined
+ // in base classes.
+ using Next::operator[];
+
+ //
+ // End of indexing support
+ //
+
+ // For parameter_requirements matching this node's key_type, return
+ // a bool constant wrapper indicating whether the requirements are
+ // satisfied by TaggedArg. Used only for compile-time computation
+ // and never really called, so a declaration is enough.
+ template <typename HasDefault, typename Predicate, typename ArgPack>
+ static typename
+#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+ ::boost::lazy_enable_if<
+ typename ::boost::mpl::if_<
+ EmitsErrors
+ , ::boost::mpl::true_
+ , _has_unique_key
+ >::type,
+#endif
+ ::boost::parameter::aux::augment_predicate<
+ Predicate
+ , reference
+ , key_type
+ , value_type
+ , ArgPack
+#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+ >
+#endif
+ >::type
+ satisfies(
+ ::boost::parameter::aux::parameter_requirements<
+ key_type
+ , Predicate
+ , HasDefault
+ >*
+ , ArgPack*
+ );
+
+ // Builds an overload set including satisfies functions defined
+ // in base classes.
+ using Next::satisfies;
+#endif // Borland workarounds needed
+
+ // Comma operator to compose argument list without using parameters<>.
+ // Useful for argument lists with undetermined length.
+ template <typename KW, typename T2>
+ inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<KW,T2>
+ , self
+ >
+ operator,(
+ ::boost::parameter::aux::tagged_argument<KW,T2> const& x
+ ) const
+ {
+ return ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<KW,T2>
+ , self
+ >(x, *this);
+ }
+
+ // MPL sequence support
+ typedef self type; // Convenience for users
+ typedef Next tail_type; // For the benefit of iterators
+ // For dispatching to sequence intrinsics
+ typedef ::boost::parameter::aux::arg_list_tag tag;
};
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
- template <class K, class T>
- T& get(default_<K,T> x) const
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename ...ArgTuples>
+ struct arg_list_cons;
+
+ template <>
+ struct arg_list_cons<>
{
- return x.value;
- }
+ using type = ::boost::parameter::aux::empty_arg_list;
+ };
- template <class K, class F>
- typename result_of0<F>::type
- get(lazy_default<K,F> x) const
+ template <typename ArgTuple0, typename ...Tuples>
+ struct arg_list_cons<ArgTuple0,Tuples...>
{
- return x.compute_default();
- }
-#endif
+ using type = ::boost::parameter::aux::arg_list<
+ typename ArgTuple0::tagged_arg
+ , typename ::boost::parameter::aux::arg_list_cons<Tuples...>::type
+ , typename ArgTuple0::emits_errors
+ >;
+ };
- // If this function is called, it means there is no argument
- // in the list that matches the supplied keyword. Just return
- // the default value.
- template <class K, class Default>
- Default& operator[](default_<K, Default> x) const
+ template <
+ typename Keyword
+ , typename TaggedArg
+ , typename EmitsErrors = ::boost::mp11::mp_true
+ >
+ struct flat_like_arg_tuple
{
- return x.value;
- }
-
- // If this function is called, it means there is no argument
- // in the list that matches the supplied keyword. Just evaluate
- // and return the default value.
- template <class K, class F>
- typename result_of0<F>::type
- operator[](
- BOOST_PARAMETER_lazy_default_fallback<K,F> x) const
+ using tagged_arg = TaggedArg;
+ using emits_errors = EmitsErrors;
+ };
+
+ template <typename ...ArgTuples>
+ class flat_like_arg_list
+ : public ::boost::parameter::aux::arg_list_cons<ArgTuples...>::type
{
- return x.compute_default();
- }
+ using _base_type = typename ::boost::parameter::aux
+ ::arg_list_cons<ArgTuples...>::type;
+
+ public:
+ inline BOOST_CONSTEXPR flat_like_arg_list(
+ typename _base_type::tagged_arg const& head
+ , typename _base_type::tail_type const& tail
+ ) : _base_type(head, tail)
+ {
+ }
- // No argument corresponding to ParameterRequirements::key_type
- // was found if we match this overload, so unless that parameter
- // has a default, we indicate that the actual arguments don't
- // match the function's requirements.
- template <class ParameterRequirements, class ArgPack>
- static typename ParameterRequirements::has_default
- satisfies(ParameterRequirements*, ArgPack*);
+ template <typename ...Args>
+ inline BOOST_CONSTEXPR flat_like_arg_list(Args&&... args)
+ : _base_type(::std::forward<Args>(args)...)
+ {
+ }
+
+ using _base_type::operator[];
+ using _base_type::satisfies;
+
+ // Comma operator to compose argument list without using parameters<>.
+ // Useful for argument lists with undetermined length.
+ template <typename TaggedArg>
+ inline BOOST_CONSTEXPR ::boost::parameter::aux::flat_like_arg_list<
+ ::boost::parameter::aux::flat_like_arg_tuple<
+ typename TaggedArg::base_type::key_type
+ , typename TaggedArg::base_type
+ >
+ , ArgTuples...
+ >
+ operator,(TaggedArg const& x) const
+ {
+ return ::boost::parameter::aux::flat_like_arg_list<
+ ::boost::parameter::aux::flat_like_arg_tuple<
+ typename TaggedArg::base_type::key_type
+ , typename TaggedArg::base_type
+ >
+ , ArgTuples...
+ >(
+ static_cast<typename TaggedArg::base_type const&>(x)
+ , static_cast<_base_type const&>(*this)
+ );
+ }
+ };
- // MPL sequence support
- typedef empty_arg_list type; // convenience
- typedef arg_list_tag tag; // For dispatching to sequence intrinsics
-};
-
-// Forward declaration for arg_list::operator,
-template <class KW, class T>
-struct tagged_argument;
-
-template <class T>
-struct get_reference
-{
- typedef typename T::reference type;
-};
-
-// A tuple of tagged arguments, terminated with empty_arg_list.
-// Every TaggedArg is an instance of tagged_argument<>.
-template <class TaggedArg, class Next = empty_arg_list>
-struct arg_list : Next
-{
- typedef arg_list<TaggedArg,Next> self;
- typedef typename TaggedArg::key_type key_type;
-
- typedef typename is_maybe<typename TaggedArg::value_type>::type holds_maybe;
-
- typedef typename mpl::eval_if<
- holds_maybe
- , get_reference<typename TaggedArg::value_type>
- , get_reference<TaggedArg>
- >::type reference;
-
- typedef typename mpl::if_<
- holds_maybe
- , reference
- , typename TaggedArg::value_type
- >::type value_type;
-
- TaggedArg arg; // Stores the argument
-
- // Store the arguments in successive nodes of this list
- template< // class A0, class A1, ...
- BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, class A)
- >
- arg_list( // A0& a0, A1& a1, ...
- BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PARAMETER_MAX_ARITY, A, & a)
- )
- : Next( // a1, a2, ...
- BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PARAMETER_MAX_ARITY, a)
- , void_reference()
- )
- , arg(a0)
- {}
-
- // Create a new list by prepending arg to a copy of tail. Used
- // when incrementally building this structure with the comma
- // operator.
- arg_list(TaggedArg head, Next const& tail)
- : Next(tail)
- , arg(head)
- {}
-
- // A metafunction class that, given a keyword and a default
- // type, returns the appropriate result type for a keyword
- // lookup given that default
- struct binding
+ template <>
+ class flat_like_arg_list<>
+ : public ::boost::parameter::aux::empty_arg_list
{
- template <class KW, class Default, class Reference>
- struct apply
+ using _base_type = ::boost::parameter::aux::empty_arg_list;
+
+ public:
+ template <typename ...Args>
+ inline BOOST_CONSTEXPR flat_like_arg_list(Args&&... args)
+ : _base_type(::std::forward<Args>(args)...)
{
- typedef typename mpl::eval_if<
- boost::is_same<KW, key_type>
- , mpl::if_<Reference, reference, value_type>
- , mpl::apply_wrap3<typename Next::binding, KW, Default, Reference>
- >::type type;
- };
+ }
+
+ using _base_type::operator[];
+ using _base_type::satisfies;
+
+ // Comma operator to compose argument list without using parameters<>.
+ // Useful for argument lists with undetermined length.
+ template <typename TaggedArg>
+ inline BOOST_CONSTEXPR ::boost::parameter::aux::flat_like_arg_list<
+ ::boost::parameter::aux::flat_like_arg_tuple<
+ typename TaggedArg::base_type::key_type
+ , typename TaggedArg::base_type
+ >
+ >
+ operator,(TaggedArg const& x) const
+ {
+ return ::boost::parameter::aux::flat_like_arg_list<
+ ::boost::parameter::aux::flat_like_arg_tuple<
+ typename TaggedArg::base_type::key_type
+ , typename TaggedArg::base_type
+ >
+ >(
+ static_cast<typename TaggedArg::base_type const&>(x)
+ , static_cast<_base_type const&>(*this)
+ );
+ }
};
+}}} // namespace boost::parameter::aux
-#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- // Overload for key_type, so the assert below will fire if the
- // same keyword is used again
- static yes_tag has_key(key_type*);
- using Next::has_key;
+#endif // BOOST_PARAMETER_CAN_USE_MP11
- BOOST_MPL_ASSERT_MSG(
- sizeof(Next::has_key((key_type*)0)) == sizeof(no_tag)
- , duplicate_keyword, (key_type)
- );
+#include <boost/mpl/iterator_tags.hpp>
-#endif
- //
- // Begin implementation of indexing operators for looking up
- // specific arguments by name
- //
+namespace boost { namespace parameter { namespace aux {
- // Helpers that handle the case when TaggedArg is
- // empty<T>.
- template <class D>
- reference get_default(D const&, mpl::false_) const
+ // MPL sequence support
+ template <typename ArgumentPack>
+ struct arg_list_iterator
{
- return arg.value;
- }
+ typedef ::boost::mpl::forward_iterator_tag category;
+
+ // The incremented iterator
+ typedef ::boost::parameter::aux
+ ::arg_list_iterator<typename ArgumentPack::tail_type> next;
- template <class D>
- reference get_default(D const& d, mpl::true_) const
+ // dereferencing yields the key type
+ typedef typename ArgumentPack::key_type type;
+ };
+
+ template <>
+ struct arg_list_iterator< ::boost::parameter::aux::empty_arg_list>
{
- return arg.value ? arg.value.get() : arg.value.construct(d.value);
- }
+ };
+}}} // namespace boost::parameter::aux
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- // These older compilers don't support the overload set creation
- // idiom well, so we need to do all the return type calculation
- // for the compiler and dispatch through an outer function template
-
- // A metafunction class that, given a keyword, returns the base
- // sublist whose get() function can produce the value for that
- // key.
- struct key_owner
+#include <boost/mpl/begin_end_fwd.hpp>
+
+// MPL sequence support
+namespace boost { namespace mpl {
+
+ template <>
+ struct begin_impl< ::boost::parameter::aux::arg_list_tag>
{
- template<class KW>
+ template <typename S>
struct apply
{
- typedef typename mpl::eval_if<
- boost::is_same<KW, key_type>
- , mpl::identity<arg_list<TaggedArg,Next> >
- , mpl::apply_wrap1<typename Next::key_owner,KW>
- >::type type;
+ typedef ::boost::parameter::aux::arg_list_iterator<S> type;
};
};
- // Outer indexing operators that dispatch to the right node's
- // get() function.
- template <class KW>
- typename mpl::apply_wrap3<binding, KW, void_, mpl::true_>::type
- operator[](keyword<KW> const& x) const
+ template <>
+ struct end_impl< ::boost::parameter::aux::arg_list_tag>
{
- typename mpl::apply_wrap1<key_owner, KW>::type const& sublist = *this;
- return sublist.get(x);
- }
+ template <typename>
+ struct apply
+ {
+ typedef ::boost::parameter::aux::arg_list_iterator<
+ ::boost::parameter::aux::empty_arg_list
+ > type;
+ };
+ };
+}} // namespace boost::mpl
- template <class KW, class Default>
- typename mpl::apply_wrap3<binding, KW, Default&, mpl::true_>::type
- operator[](default_<KW, Default> x) const
- {
- typename mpl::apply_wrap1<key_owner, KW>::type const& sublist = *this;
- return sublist.get(x);
- }
-
- template <class KW, class F>
- typename mpl::apply_wrap3<
- binding,KW
- , typename result_of0<F>::type
- , mpl::true_
- >::type
- operator[](lazy_default<KW,F> x) const
- {
- typename mpl::apply_wrap1<key_owner, KW>::type const& sublist = *this;
- return sublist.get(x);
- }
-
- // These just return the stored value; when empty_arg_list is
- // reached, indicating no matching argument was passed, the
- // default is returned, or if no default_ or lazy_default was
- // passed, compilation fails.
- reference get(keyword<key_type> const&) const
- {
- BOOST_MPL_ASSERT_NOT((holds_maybe));
- return arg.value;
- }
+#include <boost/parameter/value_type.hpp>
+#include <boost/mpl/has_key_fwd.hpp>
+#include <boost/type_traits/is_void.hpp>
- template <class Default>
- reference get(default_<key_type,Default> const& d) const
- {
- return get_default(d, holds_maybe());
- }
+namespace boost { namespace mpl {
- template <class Default>
- reference get(lazy_default<key_type, Default>) const
+ template <>
+ struct has_key_impl< ::boost::parameter::aux::arg_list_tag>
{
- return arg.value;
- }
+ template <typename ArgList, typename Keyword>
+ struct apply
+ {
+ typedef typename ::boost::mpl::if_<
+ ::boost::is_void<
+ typename ::boost::parameter
+ ::value_type<ArgList,Keyword,void>::type
+ >
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >::type type;
+ };
+ };
+}} // namespace boost::mpl
-#else
+#include <boost/mpl/count_fwd.hpp>
+#include <boost/mpl/int.hpp>
- reference operator[](keyword<key_type> const&) const
- {
- BOOST_MPL_ASSERT_NOT((holds_maybe));
- return arg.value;
- }
+namespace boost { namespace mpl {
- template <class Default>
- reference operator[](default_<key_type, Default> const& d) const
+ template <>
+ struct count_impl< ::boost::parameter::aux::arg_list_tag>
{
- return get_default(d, holds_maybe());
- }
+ template <typename ArgList, typename Keyword>
+ struct apply
+ {
+ typedef typename ::boost::mpl::if_<
+ ::boost::is_void<
+ typename ::boost::parameter
+ ::value_type<ArgList,Keyword,void>::type
+ >
+ , ::boost::mpl::int_<0>
+ , ::boost::mpl::int_<1>
+ >::type type;
+ };
+ };
+}} // namespace boost::mpl
- template <class Default>
- reference operator[](lazy_default<key_type, Default>) const
- {
- BOOST_MPL_ASSERT_NOT((holds_maybe));
- return arg.value;
- }
+#include <boost/mpl/key_type_fwd.hpp>
+#include <boost/mpl/identity.hpp>
- // Builds an overload set including operator[]s defined in base
- // classes.
- using Next::operator[];
+namespace boost { namespace mpl {
- //
- // End of indexing support
- //
+ template <>
+ struct key_type_impl< ::boost::parameter::aux::arg_list_tag>
+ {
+ template <typename ArgList, typename Keyword>
+ struct apply
+ {
+ typedef typename ::boost::mpl::eval_if<
+ ::boost::is_void<
+ typename ::boost::parameter
+ ::value_type<ArgList,Keyword,void>::type
+ >
+ , void
+ , ::boost::mpl::identity<Keyword>
+ >::type type;
+ };
+ };
+}} // namespace boost::mpl
+#include <boost/mpl/value_type_fwd.hpp>
- //
- // For parameter_requirements matching this node's key_type,
- // return a bool constant wrapper indicating whether the
- // requirements are satisfied by TaggedArg. Used only for
- // compile-time computation and never really called, so a
- // declaration is enough.
- //
- template <class HasDefault, class Predicate, class ArgPack>
- static typename mpl::apply_wrap2<
- typename mpl::lambda<Predicate, lambda_tag>::type
- , value_type, ArgPack
- >::type
- satisfies(
- parameter_requirements<key_type,Predicate,HasDefault>*
- , ArgPack*
- );
-
- // Builds an overload set including satisfies functions defined
- // in base classes.
- using Next::satisfies;
-#endif
+namespace boost { namespace mpl {
- // Comma operator to compose argument list without using parameters<>.
- // Useful for argument lists with undetermined length.
- template <class KW, class T2>
- arg_list<tagged_argument<KW, T2>, self>
- operator,(tagged_argument<KW,T2> x) const
+ template <>
+ struct value_type_impl< ::boost::parameter::aux::arg_list_tag>
+ : ::boost::mpl::key_type_impl< ::boost::parameter::aux::arg_list_tag>
{
- return arg_list<tagged_argument<KW,T2>, self>(x, *this);
- }
+ };
+}} // namespace boost::mpl
- // MPL sequence support
- typedef self type; // Convenience for users
- typedef Next tail_type; // For the benefit of iterators
- typedef arg_list_tag tag; // For dispatching to sequence intrinsics
-};
+#include <boost/mpl/at_fwd.hpp>
-// MPL sequence support
-template <class ArgumentPack>
-struct arg_list_iterator
-{
- typedef mpl::forward_iterator_tag category;
+namespace boost { namespace mpl {
- // The incremented iterator
- typedef arg_list_iterator<typename ArgumentPack::tail_type> next;
+ template <>
+ struct at_impl< ::boost::parameter::aux::arg_list_tag>
+ : ::boost::mpl::key_type_impl< ::boost::parameter::aux::arg_list_tag>
+ {
+ };
+}} // namespace boost::mpl
- // dereferencing yields the key type
- typedef typename ArgumentPack::key_type type;
-};
+#include <boost/mpl/order_fwd.hpp>
+#include <boost/mpl/void.hpp>
+#include <boost/mpl/find.hpp>
+#include <boost/mpl/distance.hpp>
-template <>
-struct arg_list_iterator<empty_arg_list> {};
+namespace boost { namespace mpl {
-}} // namespace parameter::aux
+ template <>
+ struct order_impl< ::boost::parameter::aux::arg_list_tag>
+ {
+ template <typename ArgList, typename Keyword>
+ struct apply
+ {
+ typedef typename ::boost::mpl::find<ArgList,Keyword>::type Itr;
+ typedef typename ::boost::mpl::eval_if<
+ ::boost::is_void<
+ typename ::boost::parameter
+ ::value_type<ArgList,Keyword,void>::type
+ >
+ , ::boost::mpl::identity< ::boost::mpl::void_>
+ , ::boost::mpl::distance<
+ Itr
+ , ::boost::parameter::aux::arg_list_iterator<
+ ::boost::parameter::aux::empty_arg_list
+ >
+ >
+ >::type type;
+ };
+ };
+}} // namespace boost::mpl
-// MPL sequence support
-namespace mpl
-{
- template <>
- struct begin_impl<parameter::aux::arg_list_tag>
- {
- template <class S>
- struct apply
- {
- typedef parameter::aux::arg_list_iterator<S> type;
- };
- };
-
- template <>
- struct end_impl<parameter::aux::arg_list_tag>
- {
- template <class>
- struct apply
- {
- typedef parameter::aux::arg_list_iterator<parameter::aux::empty_arg_list> type;
- };
- };
-}
-
-} // namespace boost
-
-#endif // ARG_LIST_050329_HPP
+#endif // include guard
diff --git a/boost/parameter/aux_/as_lvalue.hpp b/boost/parameter/aux_/as_lvalue.hpp
new file mode 100644
index 0000000000..d50b89778e
--- /dev/null
+++ b/boost/parameter/aux_/as_lvalue.hpp
@@ -0,0 +1,25 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_AS_LVALUE_HPP
+#define BOOST_PARAMETER_AUX_AS_LVALUE_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ T const& as_lvalue(T const& value)
+ {
+ return value;
+ }
+
+ template <typename T>
+ T& as_lvalue(T& value)
+ {
+ return value;
+ }
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/augment_predicate.hpp b/boost/parameter/aux_/augment_predicate.hpp
new file mode 100644
index 0000000000..497af08439
--- /dev/null
+++ b/boost/parameter/aux_/augment_predicate.hpp
@@ -0,0 +1,198 @@
+// Copyright Cromwell D. Enage 2018.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUGMENT_PREDICATE_HPP
+#define BOOST_PARAMETER_AUGMENT_PREDICATE_HPP
+
+#include <boost/parameter/keyword_fwd.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
+#include <boost/type_traits/is_scalar.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename V, typename R, typename Tag>
+ struct augment_predicate_check_consume_ref
+ : ::boost::mpl::eval_if<
+ ::boost::is_scalar<V>
+ , ::boost::mpl::true_
+ , ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::consume_reference
+ >
+ , ::boost::mpl::if_<
+ ::boost::is_lvalue_reference<R>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , boost::mpl::true_
+ >
+ >::type
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/type_traits/is_const.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename V, typename R, typename Tag>
+ struct augment_predicate_check_out_ref
+ : ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::mpl::eval_if<
+ ::boost::is_lvalue_reference<R>
+ , ::boost::mpl::if_<
+ ::boost::is_const<V>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::false_
+ >
+ , ::boost::mpl::true_
+ >::type
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/lambda_tag.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/mpl/lambda.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <
+ typename Predicate
+ , typename R
+ , typename Tag
+ , typename T
+ , typename Args
+ >
+ class augment_predicate
+ {
+ typedef typename ::boost::mpl::lambda<
+ Predicate
+ , ::boost::parameter::aux::lambda_tag
+ >::type _actual_predicate;
+
+ public:
+ typedef typename ::boost::mpl::eval_if<
+ typename ::boost::mpl::if_<
+ ::boost::parameter::aux
+ ::augment_predicate_check_consume_ref<T,R,Tag>
+ , ::boost::parameter::aux
+ ::augment_predicate_check_out_ref<T,R,Tag>
+ , ::boost::mpl::false_
+ >::type
+ , ::boost::mpl::apply_wrap2<_actual_predicate,T,Args>
+ , ::boost::mpl::false_
+ >::type type;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename V, typename R, typename Tag>
+ using augment_predicate_check_consume_ref_mp11 = ::boost::mp11::mp_if<
+ ::std::is_scalar<V>
+ , ::boost::mp11::mp_true
+ , ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::consume_reference
+ >
+ , ::boost::mp11::mp_if<
+ ::std::is_lvalue_reference<R>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ , boost::mp11::mp_true
+ >
+ >;
+
+ template <typename V, typename R, typename Tag>
+ using augment_predicate_check_out_ref_mp11 = ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::mp11::mp_if<
+ ::std::is_lvalue_reference<R>
+ , ::boost::mp11::mp_if<
+ ::std::is_const<V>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ , ::boost::mp11::mp_false
+ >
+ , ::boost::mp11::mp_true
+ >;
+}}} // namespace boost::parameter::aux
+
+#include <boost/mp11/list.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <
+ typename Predicate
+ , typename R
+ , typename Tag
+ , typename T
+ , typename Args
+ >
+ struct augment_predicate_mp11_impl
+ {
+ using type = ::boost::mp11::mp_if<
+ ::boost::mp11::mp_if<
+ ::boost::parameter::aux
+ ::augment_predicate_check_consume_ref_mp11<T,R,Tag>
+ , ::boost::parameter::aux
+ ::augment_predicate_check_out_ref_mp11<T,R,Tag>
+ , ::boost::mp11::mp_false
+ >
+ , ::boost::mp11
+ ::mp_apply_q<Predicate,::boost::mp11::mp_list<T,Args> >
+ , ::boost::mp11::mp_false
+ >;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/has_nested_template_fn.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <
+ typename Predicate
+ , typename R
+ , typename Tag
+ , typename T
+ , typename Args
+ >
+ using augment_predicate_mp11 = ::boost::mp11::mp_if<
+ ::boost::parameter::aux::has_nested_template_fn<Predicate>
+ , ::boost::parameter::aux
+ ::augment_predicate_mp11_impl<Predicate,R,Tag,T,Args>
+ , ::boost::parameter::aux
+ ::augment_predicate<Predicate,R,Tag,T,Args>
+ >;
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+#endif // include guard
+
diff --git a/boost/parameter/aux_/cast.hpp b/boost/parameter/aux_/cast.hpp
index bd3de2bef5..0125e2209c 100644
--- a/boost/parameter/aux_/cast.hpp
+++ b/boost/parameter/aux_/cast.hpp
@@ -1,141 +1,12 @@
-// Copyright Daniel Wallin 2006. Use, modification and distribution is
-// subject to the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARAMETER_CAST_060902_HPP
-# define BOOST_PARAMETER_CAST_060902_HPP
+#define BOOST_PARAMETER_CAST_060902_HPP
-# include <boost/detail/workaround.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/function_cast.hpp>
-# if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-# include <boost/type_traits/add_reference.hpp>
-# include <boost/type_traits/remove_const.hpp>
-# endif
-
-namespace boost { namespace parameter { namespace aux {
-
-struct use_default_tag {};
-
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-
-# define BOOST_PARAMETER_FUNCTION_CAST(value, predicate) value
-
-# else
-
-// Handles possible implicit casts. Used by preprocessor.hpp to
-// normalize user input.
-//
-// cast<void*>::execute() is identity
-// cast<void*(X)>::execute() is identity
-// cast<void(X)>::execute() casts to X
-//
-// preprocessor.hpp uses this like this:
-//
-// #define X(value, predicate)
-// cast<void predicate>::execute(value)
-//
-// X(something, *)
-// X(something, *(predicate))
-// X(something, (int))
-
-template <class T, class Args>
-struct cast;
-
-template <class Args>
-struct cast<void*, Args>
-{
- static use_default_tag execute(use_default_tag)
- {
- return use_default_tag();
- }
-
- static use_default_tag remove_const(use_default_tag)
- {
- return use_default_tag();
- }
-
- template <class U>
- static U& execute(U& value)
- {
- return value;
- }
-
- template <class U>
- static U& remove_const(U& x)
- {
- return x;
- }
-};
-
-#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580))
-
-typedef void* voidstar;
-
-template <class T, class Args>
-struct cast<voidstar(T), Args>
- : cast<void*, Args>
-{
-};
-
-#else
-
-template <class T, class Args>
-struct cast<void*(T), Args>
- : cast<void*, Args>
-{
-};
-
-#endif
-
-// This is a hack used in cast<> to turn the user supplied type,
-// which may or may not be a placeholder expression into one, so
-// that it will be properly evaluated by mpl::apply.
-template <class T, class Dummy = mpl::_1>
-struct as_placeholder_expr
-{
- typedef T type;
-};
-
-template <class T, class Args>
-struct cast<void(T), Args>
-{
- typedef typename mpl::apply2<
- as_placeholder_expr<T>, Args, Args>::type type0;
-
- typedef typename boost::add_reference<
- typename boost::remove_const<type0>::type
- >::type reference;
-
- static use_default_tag execute(use_default_tag)
- {
- return use_default_tag();
- }
-
- static use_default_tag remove_const(use_default_tag)
- {
- return use_default_tag();
- }
-
- static type0 execute(type0 value)
- {
- return value;
- }
-
- template <class U>
- static reference remove_const(U const& x)
- {
- return const_cast<reference>(x);
- }
-};
-
-# define BOOST_PARAMETER_FUNCTION_CAST(value, predicate, args) \
- boost::parameter::aux::cast<void predicate, args>::remove_const( \
- boost::parameter::aux::cast<void predicate, args>::execute(value) \
- )
-
-# endif
-
-}}} // namespace boost::parameter::aux
-
-#endif // BOOST_PARAMETER_CAST_060902_HPP
+#endif // include guard
diff --git a/boost/parameter/aux_/default.hpp b/boost/parameter/aux_/default.hpp
index 604da61299..531111c3e8 100644
--- a/boost/parameter/aux_/default.hpp
+++ b/boost/parameter/aux_/default.hpp
@@ -1,69 +1,100 @@
-// Copyright Daniel Wallin, David Abrahams 2005. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Copyright Cromwell D. Enage 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 DEFAULT_050329_HPP
-# define DEFAULT_050329_HPP
+#define DEFAULT_050329_HPP
-# include <boost/detail/workaround.hpp>
+namespace boost { namespace parameter { namespace aux {
+
+ // A wrapper for the default value passed by the user when resolving
+ // the value of the parameter with the given Keyword
+ template <typename Keyword, typename Value>
+ struct default_
+ {
+ inline BOOST_CONSTEXPR default_(Value& x) : value(x)
+ {
+ }
+
+ Value& value;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/config.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // lazy_default -- A wrapper for the default value computation function
+ // passed by the user when resolving the value of the parameter with the
+ // given keyword.
+#if BOOST_WORKAROUND(__EDG_VERSION__, <= 300)
+ // These compilers need a little extra help with overload resolution;
+ // we have empty_arg_list's operator[] accept a base class
+ // to make that overload less preferable.
+ template <typename KW, typename DefaultComputer>
+ struct lazy_default_base
+ {
+ inline BOOST_CONSTEXPR lazy_default_base(DefaultComputer& x)
+ : compute_default(x)
+ {
+ }
+
+ DefaultComputer& compute_default;
+ };
+
+ template <typename KW, typename DefaultComputer>
+ struct lazy_default
+ : ::boost::parameter::aux::lazy_default_base<KW,DefaultComputer>
+ {
+ inline BOOST_CONSTEXPR lazy_default(DefaultComputer& x)
+ : ::boost::parameter::aux::lazy_default_base<KW,DefaultComputer>(x)
+ {
+ }
+ };
+#else // !BOOST_WORKAROUND(__EDG_VERSION__, <= 300)
+ template <typename KW, typename DefaultComputer>
+ struct lazy_default
+ {
+ inline BOOST_CONSTEXPR lazy_default(DefaultComputer& x)
+ : compute_default(x)
+ {
+ }
+
+ DefaultComputer& compute_default;
+ };
+#endif // EDG workarounds needed.
+}}} // namespace boost::parameter::aux
+
+#if BOOST_WORKAROUND(__EDG_VERSION__, <= 300)
+#define BOOST_PARAMETER_lazy_default_fallback \
+ ::boost::parameter::aux::lazy_default_base
+/**/
+#else
+#define BOOST_PARAMETER_lazy_default_fallback \
+ ::boost::parameter::aux::lazy_default
+/**/
+#endif
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+#include <utility>
namespace boost { namespace parameter { namespace aux {
-// A wrapper for the default value passed by the user when resolving
-// the value of the parameter with the given Keyword
-template <class Keyword, class Value>
-struct default_
-{
- default_(Value& x)
- : value(x)
- {}
-
- Value& value;
-};
-
-//
-// lazy_default --
-//
-// A wrapper for the default value computation function passed by
-// the user when resolving the value of the parameter with the
-// given keyword
-//
-# if BOOST_WORKAROUND(__EDG_VERSION__, <= 300)
-// These compilers need a little extra help with overload
-// resolution; we have empty_arg_list's operator[] accept a base
-// class to make that overload less preferable.
-template <class KW, class DefaultComputer>
-struct lazy_default_base
-{
- lazy_default_base(DefaultComputer const& x)
- : compute_default(x)
- {}
- DefaultComputer const& compute_default;
-};
-
-template <class KW, class DefaultComputer>
-struct lazy_default
- : lazy_default_base<KW,DefaultComputer>
- {
- lazy_default(DefaultComputer const & x)
- : lazy_default_base<KW,DefaultComputer>(x)
- {}
- };
-# define BOOST_PARAMETER_lazy_default_fallback lazy_default_base
-# else
-template <class KW, class DefaultComputer>
-struct lazy_default
-{
- lazy_default(const DefaultComputer& x)
- : compute_default(x)
- {}
- DefaultComputer const& compute_default;
-};
-# define BOOST_PARAMETER_lazy_default_fallback lazy_default
-# endif
+ template <typename Keyword, typename Value>
+ struct default_r_
+ {
+ inline BOOST_CONSTEXPR default_r_(Value&& x)
+ : value(::std::forward<Value>(x))
+ {
+ }
+ Value&& value;
+ };
}}} // namespace boost::parameter::aux
-#endif // DEFAULT_050329_HPP
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+#endif // include guard
diff --git a/boost/parameter/aux_/has_nested_template_fn.hpp b/boost/parameter/aux_/has_nested_template_fn.hpp
new file mode 100644
index 0000000000..e68857d572
--- /dev/null
+++ b/boost/parameter/aux_/has_nested_template_fn.hpp
@@ -0,0 +1,111 @@
+// Copyright Cromwell D. Enage 2019.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_HAS_NESTED_TEMPLATE_FN_HPP
+#define BOOST_PARAMETER_AUX_HAS_NESTED_TEMPLATE_FN_HPP
+
+#include <boost/parameter/aux_/yesno.hpp>
+#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/identity.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <template <typename ...> class F>
+ struct has_nested_template_fn_variadic
+ {
+ };
+#else
+ template <template <typename P0, typename P1> class F>
+ struct has_nested_template_fn_arity_2
+ {
+ };
+#endif
+
+ template <typename T>
+ class has_nested_template_fn_impl
+ {
+ template <typename U>
+ static ::boost::parameter::aux::no_tag _check(...);
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename U>
+ static ::boost::parameter::aux::yes_tag
+ _check(
+ ::boost::mp11::mp_identity<U> const volatile*
+ , ::boost::parameter::aux::has_nested_template_fn_variadic<
+ U::template fn
+ >* = BOOST_PARAMETER_AUX_PP_NULLPTR
+ );
+#else
+ template <typename U>
+ static BOOST_CONSTEXPR ::boost::parameter::aux::yes_tag
+ _check(
+ ::boost::mpl::identity<U> const volatile*
+ , ::boost::parameter::aux::has_nested_template_fn_arity_2<
+ U::template fn
+ >* = BOOST_PARAMETER_AUX_PP_NULLPTR
+ );
+#endif
+
+ public:
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_bool<
+#else
+ typedef ::boost::mpl::bool_<
+#endif
+ sizeof(
+ ::boost::parameter::aux::has_nested_template_fn_impl<T>
+ ::template _check<T>(
+ static_cast<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_identity<T> const volatile*
+#else
+ ::boost::mpl::identity<T> const volatile*
+#endif
+ >(BOOST_PARAMETER_AUX_PP_NULLPTR)
+ )
+ ) == sizeof(::boost::parameter::aux::yes_tag)
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >;
+#else
+ > type;
+#endif
+ };
+}}} // namespace boost::parameter::aux
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <type_traits>
+#else
+#include <boost/type_traits/remove_const.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using has_nested_template_fn = typename ::boost::parameter::aux
+ ::has_nested_template_fn_impl<typename ::std::remove_const<T>::type>
+ ::type;
+#else
+ struct has_nested_template_fn
+ : ::boost::parameter::aux::has_nested_template_fn_impl<
+ typename ::boost::remove_const<T>::type
+ >::type
+ {
+ };
+#endif
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/is_maybe.hpp b/boost/parameter/aux_/is_maybe.hpp
index b875852847..0069eddc14 100644
--- a/boost/parameter/aux_/is_maybe.hpp
+++ b/boost/parameter/aux_/is_maybe.hpp
@@ -1,26 +1,52 @@
-// Copyright Daniel Wallin, David Abrahams 2010. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
+// Copyright Daniel Wallin, David Abrahams 2010.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARAMETER_IS_MAYBE_050329_HPP
#define BOOST_PARAMETER_IS_MAYBE_050329_HPP
-#include <boost/type_traits/is_base_and_derived.hpp>
+namespace boost { namespace parameter { namespace aux {
-namespace boost {
-namespace parameter {
-namespace aux {
+ struct maybe_base
+ {
+ };
+}}} // namespace boost::parameter::aux
-struct maybe_base {};
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <type_traits>
-template <class T>
-struct is_maybe
- : is_base_and_derived<maybe_base, T>
-{};
+namespace boost { namespace parameter { namespace aux {
-} // namespace aux
-} // namespace parameter
-} // namespace boost
+ template <typename T>
+ using is_maybe = ::std::is_base_of<
+ ::boost::parameter::aux::maybe_base
+ , typename ::std::remove_const<T>::type
+ >;
+}}} // namespace boost::parameter::aux
+
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ struct is_maybe
+ : ::boost::mpl::if_<
+ ::boost::is_base_of<
+ ::boost::parameter::aux::maybe_base
+ , typename ::boost::remove_const<T>::type
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >::type
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+#endif // include guard
-#endif // BOOST_PARAMETER_IS_MAYBE_050329_HPP
diff --git a/boost/parameter/aux_/is_placeholder.hpp b/boost/parameter/aux_/is_placeholder.hpp
new file mode 100644
index 0000000000..2ed46d86af
--- /dev/null
+++ b/boost/parameter/aux_/is_placeholder.hpp
@@ -0,0 +1,64 @@
+// Copyright Cromwell D. Enage 2019.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_IS_PLACEHOLDER_HPP
+#define BOOST_PARAMETER_AUX_IS_PLACEHOLDER_HPP
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#else
+#include <boost/mpl/bool.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ struct is_mpl_placeholder
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_false
+#else
+ : ::boost::mpl::false_
+#endif
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/mpl/arg_fwd.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <int I>
+ struct is_mpl_placeholder< ::boost::mpl::arg<I> >
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_true
+#else
+ : ::boost::mpl::true_
+#endif
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/bind.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ struct is_mp11_placeholder : ::boost::mp11::mp_false
+ {
+ };
+
+ template < ::std::size_t I>
+ struct is_mp11_placeholder< ::boost::mp11::mp_arg<I> >
+ : ::boost::mp11::mp_true
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+#endif // include guard
+
diff --git a/boost/parameter/aux_/is_tagged_argument.hpp b/boost/parameter/aux_/is_tagged_argument.hpp
new file mode 100644
index 0000000000..fa1b53d8cf
--- /dev/null
+++ b/boost/parameter/aux_/is_tagged_argument.hpp
@@ -0,0 +1,95 @@
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Copyright Cromwell D. Enage 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_PARAMETER_IS_TAGGED_ARGUMENT_HPP
+#define BOOST_PARAMETER_IS_TAGGED_ARGUMENT_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ struct tagged_argument_base
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/config.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) || \
+ (0 < BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY)
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // This metafunction identifies tagged_argument specializations
+ // and their derived classes.
+ template <typename T>
+ struct is_tagged_argument
+ : ::boost::mpl::if_<
+ // Cannot use is_convertible<> to check if T is derived from
+ // tagged_argument_base. -- Cromwell D. Enage
+ ::boost::is_base_of<
+ ::boost::parameter::aux::tagged_argument_base
+ , typename ::boost::remove_const<
+ typename ::boost::remove_reference<T>::type
+ >::type
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >::type
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#else // no perfect forwarding support and no exponential overloads
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ struct is_tagged_argument_aux
+ : ::boost::is_convertible<
+ T*
+ , ::boost::parameter::aux::tagged_argument_base const*
+ >
+ {
+ };
+
+ // This metafunction identifies tagged_argument specializations
+ // and their derived classes.
+ template <typename T>
+ struct is_tagged_argument
+ : ::boost::mpl::if_<
+ ::boost::is_lvalue_reference<T>
+ , ::boost::mpl::false_
+ , ::boost::parameter::aux::is_tagged_argument_aux<T>
+ >::type
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // perfect forwarding support, or exponential overloads
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <type_traits>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ using is_tagged_argument_mp11 = ::std::is_base_of<
+ ::boost::parameter::aux::tagged_argument_base
+ , typename ::std::remove_const<
+ typename ::std::remove_reference<T>::type
+ >::type
+ >;
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+#endif // include guard
+
diff --git a/boost/parameter/aux_/lambda_tag.hpp b/boost/parameter/aux_/lambda_tag.hpp
new file mode 100644
index 0000000000..77759a2e7d
--- /dev/null
+++ b/boost/parameter/aux_/lambda_tag.hpp
@@ -0,0 +1,16 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_LAMBDA_TAG_HPP
+#define BOOST_PARAMETER_AUX_LAMBDA_TAG_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Tag type passed to MPL lambda.
+ struct lambda_tag;
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/maybe.hpp b/boost/parameter/aux_/maybe.hpp
index 55e083e5b4..74273fcf3d 100644
--- a/boost/parameter/aux_/maybe.hpp
+++ b/boost/parameter/aux_/maybe.hpp
@@ -1,120 +1,151 @@
-// Copyright Daniel Wallin 2006. Use, modification and distribution is
-// subject to the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
//
// 2009.10.21 TDS remove depenency on boost::python::detail::referent_storage
//
#ifndef BOOST_PARAMETER_MAYBE_091021_HPP
-# define BOOST_PARAMETER_MAYBE_091021_HPP
-
-# include <boost/mpl/if.hpp>
-# include <boost/mpl/identity.hpp>
-# include <boost/type_traits/is_reference.hpp>
-# include <boost/type_traits/add_reference.hpp>
-# include <boost/optional.hpp>
-# include <boost/aligned_storage.hpp>
-# include <boost/type_traits/remove_cv.hpp>
-# include <boost/type_traits/add_const.hpp>
-# include <boost/parameter/aux_/is_maybe.hpp>
+#define BOOST_PARAMETER_MAYBE_091021_HPP
namespace boost { namespace parameter { namespace aux {
-template <class T> struct referent_size;
-
-template <class T>
-struct referent_size<T&>
-{
- BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(T));
-};
-
-// A metafunction returning a POD type which can store U, where T ==
-// U&. If T is not a reference type, returns a POD which can store T.
-template <class T>
-struct referent_storage
-{
- typedef typename boost::aligned_storage<
- referent_size<T>::value
- >::type type;
-};
-
-template <class T>
-struct maybe : maybe_base
-{
- typedef typename add_reference<
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- T const
-# else
- typename add_const<T>::type
-# endif
- >::type reference;
-
- typedef typename remove_cv<
- BOOST_DEDUCED_TYPENAME remove_reference<reference>::type
- >::type non_cv_value;
-
- explicit maybe(T value_)
- : value(value_)
- , constructed(false)
- {}
-
- maybe()
- : constructed(false)
- {}
-
- ~maybe()
- {
- if (constructed)
- this->destroy();
- }
+ template <typename T>
+ struct referent_size;
+}}} // namespace boost::parameter::aux
- reference construct(reference value_) const
- {
- return value_;
- }
+#include <boost/parameter/config.hpp>
- template <class U>
- reference construct2(U const& value_) const
- {
- new (m_storage.address()) non_cv_value(value_);
- constructed = true;
- return *(non_cv_value*)m_storage.address();
- }
-
- template <class U>
- reference construct(U const& value_) const
- {
- return this->construct2(value_);
- }
+namespace boost { namespace parameter { namespace aux {
- void destroy()
+ template <typename T>
+ struct referent_size<T&>
{
- ((non_cv_value*)m_storage.address())->~non_cv_value();
- }
+ BOOST_STATIC_CONSTANT(::std::size_t, value = sizeof(T));
+ };
+}}} // namespace boost::parameter::aux
- typedef reference(maybe<T>::*safe_bool)() const;
+#include <boost/type_traits/aligned_storage.hpp>
- operator safe_bool() const
- {
- return value ? &maybe<T>::get : 0 ;
- }
+namespace boost { namespace parameter { namespace aux {
- reference get() const
+ // A metafunction returning a POD type which can store U, where T == U&.
+ // If T is not a reference type, returns a POD which can store T.
+ template <typename T>
+ struct referent_storage
+ : ::boost::aligned_storage<
+ ::boost::parameter::aux::referent_size<T>::value
+ >
{
- return value.get();
- }
+ };
+}}} // namespace boost::parameter::aux
-private:
- boost::optional<T> value;
- mutable bool constructed;
+#include <boost/parameter/aux_/is_maybe.hpp>
+#include <boost/optional/optional.hpp>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <type_traits>
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/type_traits/add_lvalue_reference.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+#include <boost/type_traits/add_const.hpp>
+#endif
+#endif // BOOST_PARAMETER_CAN_USE_MP11
- mutable typename referent_storage<
- reference
- >::type m_storage;
-};
+namespace boost { namespace parameter { namespace aux {
+ template <typename T>
+ struct maybe : ::boost::parameter::aux::maybe_base
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typedef typename ::std::add_lvalue_reference<
+ typename ::std::add_const<T>::type
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typedef typename ::boost::add_lvalue_reference<
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ T const
+#else
+ typename ::boost::add_const<T>::type
+#endif
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ >::type reference;
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typedef typename ::std::remove_cv<
+ typename ::std::remove_reference<reference>::type
+#else
+ typedef typename ::boost::remove_cv<
+ BOOST_DEDUCED_TYPENAME ::boost::remove_reference<reference>::type
+#endif
+ >::type non_cv_value;
+
+ inline explicit maybe(T value_) : value(value_), constructed(false)
+ {
+ }
+
+ inline maybe() : value(), constructed(false)
+ {
+ }
+
+ ~maybe()
+ {
+ if (this->constructed)
+ {
+ this->destroy();
+ }
+ }
+
+ inline reference construct(reference value_) const
+ {
+ return value_;
+ }
+
+ template <typename U>
+ reference construct2(U const& value_) const
+ {
+ new (this->m_storage.address()) non_cv_value(value_);
+ this->constructed = true;
+ return *reinterpret_cast<non_cv_value*>(
+ this->m_storage.address()
+ );
+ }
+
+ template <typename U>
+ inline reference construct(U const& value_) const
+ {
+ return this->construct2(value_);
+ }
+
+ void destroy()
+ {
+ reinterpret_cast<non_cv_value*>(
+ this->m_storage.address()
+ )->~non_cv_value();
+ }
+
+ typedef reference(
+ ::boost::parameter::aux::maybe<T>::*safe_bool
+ )() const;
+
+ inline operator safe_bool() const
+ {
+ return this->value ? &::boost::parameter::aux::maybe<T>::get : 0;
+ }
+
+ inline reference get() const
+ {
+ return this->value.get();
+ }
+
+ private:
+ ::boost::optional<T> value;
+ mutable bool constructed;
+ mutable typename ::boost::parameter::aux
+ ::referent_storage<reference>::type m_storage;
+ };
}}} // namespace boost::parameter::aux
-#endif // BOOST_PARAMETER_MAYBE_060211_HPP
+#endif // include guard
diff --git a/boost/parameter/aux_/name.hpp b/boost/parameter/aux_/name.hpp
new file mode 100644
index 0000000000..8d623bcabf
--- /dev/null
+++ b/boost/parameter/aux_/name.hpp
@@ -0,0 +1,93 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_NAME_HPP
+#define BOOST_PARAMETER_AUX_NAME_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ struct name_tag_base
+ {
+ };
+
+ template <typename Tag>
+ struct name_tag
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/mpl/bool.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ struct is_name_tag : ::boost::mpl::false_
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/value_type.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+#if !defined(BOOST_NO_SFINAE) && \
+ !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
+#include <boost/parameter/aux_/lambda_tag.hpp>
+#include <boost/mpl/lambda.hpp>
+#include <boost/mpl/bind.hpp>
+#include <boost/mpl/quote.hpp>
+#include <boost/core/enable_if.hpp>
+
+namespace boost { namespace mpl {
+
+ template <typename T>
+ struct lambda<
+ T
+ , typename ::boost::enable_if<
+ ::boost::parameter::aux::is_name_tag<T>
+ , ::boost::parameter::aux::lambda_tag
+ >::type
+ >
+ {
+ typedef ::boost::mpl::true_ is_le;
+ typedef ::boost::mpl::bind3<
+ ::boost::mpl::quote3< ::boost::parameter::value_type>
+ , ::boost::mpl::arg<2>
+ , T
+ , void
+ > result_;
+ typedef result_ type;
+ };
+}} // namespace boost::mpl
+
+#endif // SFINAE enabled, not Borland.
+
+#include <boost/parameter/aux_/void.hpp>
+
+#define BOOST_PARAMETER_TAG_PLACEHOLDER_TYPE(tag) \
+ ::boost::parameter::value_type< \
+ ::boost::mpl::_2,tag,::boost::parameter::void_ \
+ >
+/**/
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_TAG_MP11_PLACEHOLDER_VALUE(name, tag) \
+ template <typename ArgumentPack> \
+ using name = typename ::boost::parameter \
+ ::value_type<ArgumentPack,tag,::boost::parameter::void_>::type
+/**/
+
+#include <boost/parameter/binding.hpp>
+
+#define BOOST_PARAMETER_TAG_MP11_PLACEHOLDER_BINDING(name, tag) \
+ template <typename ArgumentPack> \
+ using name = typename ::boost::parameter \
+ ::binding<ArgumentPack,tag,::boost::parameter::void_>::type
+/**/
+
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+#endif // include guard
+
diff --git a/boost/parameter/aux_/overloads.hpp b/boost/parameter/aux_/overloads.hpp
deleted file mode 100644
index dcc92d4d75..0000000000
--- a/boost/parameter/aux_/overloads.hpp
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright David Abrahams, Daniel Wallin 2003. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// This file generates overloads in this format:
-//
-// template<class A0, class A1>
-// typename mpl::apply_wrap1<
-// aux::make_arg_list<
-// PS0,A0
-// , aux::make_arg_list<
-// PS1,A1
-// , mpl::identity<aux::empty_arg_list>
-// >
-// >
-// , unnamed_list
-// >::type
-// operator()(A0 const& a0, A1 const& a1) const
-// {
-// typedef typename mpl::apply_wrap1<
-// aux::make_arg_list<
-// PS0,A0
-// , aux::make_arg_list<
-// PS1,A1
-// , mpl::identity<aux::empty_arg_list>
-// >
-// >
-// >::type arg_tuple;
-//
-// return arg_tuple(
-// a0
-// , a1
-// , aux::void_()
-// ...
-// );
-// }
-//
-
-#if !defined(BOOST_PP_IS_ITERATING)
-# error Boost.Parameters - do not include this file!
-#endif
-
-#define N BOOST_PP_ITERATION()
-
-#define BOOST_PARAMETER_open_list(z, n, text) \
- aux::item< \
- BOOST_PP_CAT(PS, n), BOOST_PP_CAT(A, n)
-
-#define BOOST_PARAMETER_close_list(z, n, text) >
-
-#define BOOST_PARAMETER_arg_list(n) \
- aux::make_arg_list< \
- BOOST_PP_ENUM(N, BOOST_PARAMETER_open_list, _) \
- , void_ \
- BOOST_PP_REPEAT(N, BOOST_PARAMETER_close_list, _) \
- , deduced_list \
- , aux::tag_keyword_arg \
- >
-
-#define BOOST_PARAMETER_arg_pack_init(z, n, limit) \
- BOOST_PP_CAT(a, BOOST_PP_SUB(limit,n))
-
-template<BOOST_PP_ENUM_PARAMS(N, class A)>
-typename mpl::first<
- typename BOOST_PARAMETER_arg_list(N)::type
->::type
-operator()(BOOST_PP_ENUM_BINARY_PARAMS(N, A, & a)) const
-{
- typedef typename BOOST_PARAMETER_arg_list(N)::type result;
-
- typedef typename mpl::first<result>::type result_type;
- typedef typename mpl::second<result>::type error;
- error();
-
- return result_type(
- BOOST_PP_ENUM(N, BOOST_PARAMETER_arg_pack_init, BOOST_PP_DEC(N))
- BOOST_PP_ENUM_TRAILING_PARAMS(
- BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, N)
- , aux::void_reference() BOOST_PP_INTERCEPT
- ));
-}
-
-#undef BOOST_PARAMETER_arg_list
-#undef BOOST_PARAMETER_open_list
-#undef BOOST_PARAMETER_close_list
-#undef N
-
diff --git a/boost/parameter/aux_/pack/as_parameter_requirements.hpp b/boost/parameter/aux_/pack/as_parameter_requirements.hpp
new file mode 100644
index 0000000000..65fae4c7ee
--- /dev/null
+++ b/boost/parameter/aux_/pack/as_parameter_requirements.hpp
@@ -0,0 +1,32 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_AS_PARAMETER_REQUIREMENTS_HPP
+#define BOOST_PARAMETER_AUX_PACK_AS_PARAMETER_REQUIREMENTS_HPP
+
+#include <boost/parameter/aux_/pack/parameter_requirements.hpp>
+#include <boost/parameter/aux_/pack/tag_type.hpp>
+#include <boost/parameter/aux_/pack/predicate.hpp>
+#include <boost/parameter/deduced.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Converts a ParameterSpec into a specialization of
+ // parameter_requirements. We need to do this in order to get the
+ // tag_type into the type in a way that can be conveniently matched
+ // by a satisfies(...) member function in arg_list.
+ template <typename ParameterSpec>
+ struct as_parameter_requirements
+ {
+ typedef ::boost::parameter::aux::parameter_requirements<
+ typename ::boost::parameter::aux::tag_type<ParameterSpec>::type
+ , typename ::boost::parameter::aux::predicate<ParameterSpec>::type
+ , ::boost::parameter::aux::has_default<ParameterSpec>
+ > type;
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/deduce_tag.hpp b/boost/parameter/aux_/pack/deduce_tag.hpp
new file mode 100644
index 0000000000..12ad563f53
--- /dev/null
+++ b/boost/parameter/aux_/pack/deduce_tag.hpp
@@ -0,0 +1,217 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_DEDUCE_TAG_HPP
+#define BOOST_PARAMETER_AUX_PACK_DEDUCE_TAG_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <
+ typename Argument
+ , typename ArgumentPack
+ , typename DeducedArgs
+ , typename UsedArgs
+ , typename TagFn
+ , typename EmitsErrors
+ >
+ struct deduce_tag;
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/lambda_tag.hpp>
+#include <boost/parameter/config.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/mpl/lambda.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Predicate, typename Argument, typename ArgumentPack>
+ struct deduce_tag_condition_mpl
+ : ::boost::mpl::apply_wrap2<
+ typename ::boost::mpl::lambda<
+ Predicate
+ , ::boost::parameter::aux::lambda_tag
+ >::type
+ , Argument
+ , ArgumentPack
+ >
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/has_nested_template_fn.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Predicate, typename Argument, typename ArgumentPack>
+ struct deduce_tag_condition_mp11
+ {
+ using type = ::boost::mp11::mp_apply_q<
+ Predicate
+ , ::boost::mp11::mp_list<Argument,ArgumentPack>
+ >;
+ };
+
+ template <typename Predicate, typename Argument, typename ArgumentPack>
+ using deduce_tag_condition = ::boost::mp11::mp_if<
+ ::boost::parameter::aux::has_nested_template_fn<Predicate>
+ , ::boost::parameter::aux
+ ::deduce_tag_condition_mp11<Predicate,Argument,ArgumentPack>
+ , ::boost::parameter::aux
+ ::deduce_tag_condition_mpl<Predicate,Argument,ArgumentPack>
+ >;
+}}} // namespace boost::parameter::aux
+
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/assert.hpp>
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+#include <boost/parameter/aux_/set.hpp>
+#include <boost/parameter/aux_/pack/tag_type.hpp>
+#include <boost/parameter/aux_/pack/tag_deduced.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Helper for deduce_tag<...>, below.
+ template <
+ typename Argument
+ , typename ArgumentPack
+ , typename DeducedArgs
+ , typename UsedArgs
+ , typename TagFn
+ , typename EmitsErrors
+ >
+ class deduce_tag0
+ {
+ typedef typename DeducedArgs::spec _spec;
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typedef typename ::boost::parameter::aux::deduce_tag_condition<
+ typename _spec::predicate
+#else
+ typedef typename ::boost::mpl::apply_wrap2<
+ typename ::boost::mpl::lambda<
+ typename _spec::predicate
+ , ::boost::parameter::aux::lambda_tag
+ >::type
+#endif
+ , Argument
+ , ArgumentPack
+ >::type _condition;
+
+#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ // Deduced parameter matches several arguments.
+ BOOST_MPL_ASSERT((
+ typename ::boost::mpl::eval_if<
+ typename ::boost::parameter::aux::has_key_<
+ UsedArgs
+ , typename ::boost::parameter::aux::tag_type<_spec>::type
+ >::type
+ , ::boost::mpl::eval_if<
+ _condition
+ , ::boost::mpl::if_<
+ EmitsErrors
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::true_
+ >::type
+ ));
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+ public:
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = typename ::boost::mp11::mp_if<
+#else
+ typedef typename ::boost::mpl::eval_if<
+#endif
+ _condition
+ , ::boost::parameter::aux
+ ::tag_deduced<UsedArgs,_spec,Argument,TagFn>
+ , ::boost::parameter::aux::deduce_tag<
+ Argument
+ , ArgumentPack
+ , typename DeducedArgs::tail
+ , UsedArgs
+ , TagFn
+ , EmitsErrors
+ >
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >::type;
+#else
+ >::type type;
+#endif
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/void.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <type_traits>
+#else
+#include <boost/mpl/pair.hpp>
+#include <boost/type_traits/is_same.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Tries to deduced a keyword tag for a given Argument.
+ // Returns an mpl::pair<> consisting of the tagged_argument<>,
+ // and an mpl::set<> where the new tag has been inserted.
+ //
+ // Argument: The argument type to be tagged.
+ //
+ // ArgumentPack: The ArgumentPack built so far.
+ //
+ // DeducedArgs: A specialization of deduced_item<> (see below).
+ // A list containing only the deduced ParameterSpecs.
+ //
+ // UsedArgs: An mpl::set<> containing the keyword tags used so far.
+ //
+ // TagFn: A metafunction class used to tag positional or deduced
+ // arguments with a keyword tag.
+ template <
+ typename Argument
+ , typename ArgumentPack
+ , typename DeducedArgs
+ , typename UsedArgs
+ , typename TagFn
+ , typename EmitsErrors
+ >
+ struct deduce_tag
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_if<
+ ::std::is_same<DeducedArgs,::boost::parameter::void_>
+ , ::boost::mp11::mp_identity<
+ ::boost::mp11::mp_list< ::boost::parameter::void_,UsedArgs>
+ >
+#else
+ : ::boost::mpl::eval_if<
+ ::boost::is_same<DeducedArgs,::boost::parameter::void_>
+ , ::boost::mpl::pair< ::boost::parameter::void_,UsedArgs>
+#endif
+ , ::boost::parameter::aux::deduce_tag0<
+ Argument
+ , ArgumentPack
+ , DeducedArgs
+ , UsedArgs
+ , TagFn
+ , EmitsErrors
+ >
+ >
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/deduced_item.hpp b/boost/parameter/aux_/pack/deduced_item.hpp
new file mode 100644
index 0000000000..280e6eac6a
--- /dev/null
+++ b/boost/parameter/aux_/pack/deduced_item.hpp
@@ -0,0 +1,34 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_DEDUCED_ITEM_HPP
+#define BOOST_PARAMETER_AUX_PACK_DEDUCED_ITEM_HPP
+
+#include <boost/parameter/aux_/void.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // A typelist that stored deduced parameter specs.
+ template <
+ typename ParameterSpec
+ , typename Tail = ::boost::parameter::void_
+ >
+ struct deduced_item
+ {
+ typedef ParameterSpec spec;
+ typedef Tail tail;
+ };
+
+ // Evaluate Tail and construct deduced_item list.
+ template <typename Spec, typename Tail>
+ struct make_deduced_item
+ {
+ typedef ::boost::parameter::aux
+ ::deduced_item<Spec,typename Tail::type> type;
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/insert_tagged.hpp b/boost/parameter/aux_/pack/insert_tagged.hpp
new file mode 100644
index 0000000000..bef47b14db
--- /dev/null
+++ b/boost/parameter/aux_/pack/insert_tagged.hpp
@@ -0,0 +1,23 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_INSERT_TAGGED_HPP
+#define BOOST_PARAMETER_AUX_PACK_INSERT_TAGGED_HPP
+
+#include <boost/parameter/aux_/set.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Inserts Tagged::key_type into the UserArgs set.
+ // Extra indirection to lazily evaluate Tagged::key_type.
+ template <typename UsedArgs, typename Tagged>
+ struct insert_tagged
+ : ::boost::parameter::aux::insert_<UsedArgs,typename Tagged::key_type>
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/is_named_argument.hpp b/boost/parameter/aux_/pack/is_named_argument.hpp
new file mode 100644
index 0000000000..8b93f61c25
--- /dev/null
+++ b/boost/parameter/aux_/pack/is_named_argument.hpp
@@ -0,0 +1,43 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_IS_NAMED_ARGUMENT_HPP
+#define BOOST_PARAMETER_AUX_PACK_IS_NAMED_ARGUMENT_HPP
+
+#include <boost/parameter/aux_/template_keyword.hpp>
+#include <boost/parameter/aux_/is_tagged_argument.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using is_named_argument = ::boost::mp11::mp_if<
+ ::boost::parameter::aux::is_template_keyword<T>
+ , ::boost::mp11::mp_true
+ , ::boost::parameter::aux::is_tagged_argument_mp11<T>
+ >;
+#else
+ struct is_named_argument
+ : ::boost::mpl::if_<
+ ::boost::parameter::aux::is_template_keyword<T>
+ , ::boost::mpl::true_
+ , ::boost::parameter::aux::is_tagged_argument<T>
+ >::type
+ {
+ };
+#endif
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/item.hpp b/boost/parameter/aux_/pack/item.hpp
new file mode 100644
index 0000000000..b408051bad
--- /dev/null
+++ b/boost/parameter/aux_/pack/item.hpp
@@ -0,0 +1,47 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_ITEM_HPP
+#define BOOST_PARAMETER_AUX_PACK_ITEM_HPP
+
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ // A parameter spec item typelist.
+ template <
+ typename Spec
+ , typename Arg
+ , typename Tail = ::boost::parameter::void_
+ >
+ struct item
+ {
+ typedef Spec spec;
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ typedef ::boost::is_const<
+ typename ::boost::remove_reference<Arg>::type
+ > is_arg_const;
+#endif
+ typedef Arg arg;
+ typedef Tail tail;
+ };
+
+ template <typename Spec, typename Arg, typename Tail>
+ struct make_item
+ {
+ typedef boost::parameter::aux
+ ::item<Spec,Arg,typename Tail::type> type;
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/make_arg_list.hpp b/boost/parameter/aux_/pack/make_arg_list.hpp
new file mode 100644
index 0000000000..c43ac5c42e
--- /dev/null
+++ b/boost/parameter/aux_/pack/make_arg_list.hpp
@@ -0,0 +1,438 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Copyright Cromwell D. Enage 2018.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_MAKE_ARG_LIST_HPP
+#define BOOST_PARAMETER_AUX_PACK_MAKE_ARG_LIST_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <
+ typename List
+ , typename DeducedArgs
+ , typename TagFn
+ , typename IsPositional
+ , typename UsedArgs
+ , typename ArgumentPack
+ , typename Error
+ , typename EmitsErrors
+ >
+ struct make_arg_list_aux;
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/arg_list.hpp>
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/parameter/aux_/pack/unmatched_argument.hpp>
+#include <boost/parameter/aux_/pack/tag_type.hpp>
+#include <boost/parameter/aux_/pack/is_named_argument.hpp>
+#include <boost/parameter/aux_/pack/insert_tagged.hpp>
+#include <boost/parameter/aux_/pack/deduce_tag.hpp>
+#include <boost/parameter/deduced.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/pair.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename ArgumentPack, typename TaggedArg, typename EmitsErrors>
+ struct append_to_make_arg_list
+ {
+ using type = ::boost::mp11::mp_push_front<
+ ArgumentPack
+ , ::boost::parameter::aux::flat_like_arg_tuple<
+ typename TaggedArg::key_type
+ , TaggedArg
+ , EmitsErrors
+ >
+ >;
+ };
+#endif
+
+ // Borland needs the insane extra-indirection workaround below so that
+ // it doesn't magically drop the const qualifier from the argument type.
+ template <
+ typename List
+ , typename DeducedArgs
+ , typename TagFn
+ , typename IsPositional
+ , typename UsedArgs
+ , typename ArgumentPack
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ , typename _argument
+#endif
+ , typename Error
+ , typename EmitsErrors
+ >
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ class make_arg_list00
+#else
+ class make_arg_list0
+#endif
+ {
+#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ typedef typename List::arg _argument;
+#endif
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using _arg_type = typename ::std::remove_const<
+ typename ::std::remove_reference<_argument>::type
+ >::type;
+ using _is_tagged = ::boost::parameter::aux
+ ::is_named_argument<_argument>;
+#else
+ typedef typename ::boost::remove_const<
+ typename ::boost::remove_reference<_argument>::type
+ >::type _arg_type;
+ typedef ::boost::parameter::aux
+ ::is_named_argument<_argument> _is_tagged;
+#endif
+ typedef typename List::spec _parameter_spec;
+ typedef typename ::boost::parameter::aux
+ ::tag_type<_parameter_spec>::type _tag;
+
+ // If this argument is either explicitly tagged or a deduced
+ // parameter, then turn off positional matching.
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using _is_positional = ::boost::mp11::mp_if<
+ IsPositional
+ , ::boost::mp11::mp_if<
+ ::boost::parameter::aux::is_deduced<_parameter_spec>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_if<
+ _is_tagged
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ >
+ , ::boost::mp11::mp_false
+ >;
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typedef typename ::boost::mpl::eval_if<
+ IsPositional
+ , ::boost::mpl::eval_if<
+ ::boost::parameter::aux::is_deduced<_parameter_spec>
+ , ::boost::mpl::false_
+ , ::boost::mpl::if_<
+ _is_tagged
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ >
+ , ::boost::mpl::false_
+ >::type _is_positional;
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+ // If this parameter is explicitly tagged, then add it to the
+ // used-parmeters set. We only really need to add parameters
+ // that are deduced, but we would need a way to check if
+ // a given tag corresponds to a deduced parameter spec.
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using _used_args = typename ::boost::mp11::mp_if<
+ _is_tagged
+ , ::boost::parameter::aux::insert_tagged<UsedArgs,_arg_type>
+ , ::boost::mp11::mp_identity<UsedArgs>
+ >::type;
+#else
+ typedef typename ::boost::mpl::eval_if<
+ _is_tagged
+ , ::boost::parameter::aux::insert_tagged<UsedArgs,_arg_type>
+ , ::boost::mpl::identity<UsedArgs>
+ >::type _used_args;
+#endif
+
+ // If this parameter is neither explicitly tagged nor positionally
+ // matched, then deduce the tag from the deduced parameter specs.
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using _deduced_data = typename ::boost::mp11::mp_if<
+ ::boost::mp11::mp_if<
+ _is_tagged
+ , ::boost::mp11::mp_true
+ , _is_positional
+ >
+ , ::boost::mp11::mp_identity<
+ ::boost::mp11::mp_list< ::boost::parameter::void_,_used_args>
+ >
+#else
+ typedef typename ::boost::mpl::eval_if<
+ typename ::boost::mpl::if_<
+ _is_tagged
+ , ::boost::mpl::true_
+ , _is_positional
+ >::type
+ , ::boost::mpl::pair< ::boost::parameter::void_,_used_args>
+#endif
+ , ::boost::parameter::aux::deduce_tag<
+ _argument
+ , ArgumentPack
+ , DeducedArgs
+ , _used_args
+ , TagFn
+ , EmitsErrors
+ >
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >::type;
+#else
+ >::type _deduced_data;
+#endif
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ // If this parameter is explicitly tagged ...
+ using _tagged = ::boost::mp11::mp_if<
+ _is_tagged
+ // ... just use it
+ , _arg_type
+ // ... else ...
+ , ::boost::mp11::mp_if<
+ // if positional matching is turned on ...
+ _is_positional
+ // ... tag it positionally
+ , ::boost::mp11::mp_apply_q<
+ TagFn
+ , ::boost::mp11::mp_list<_tag,_argument>
+ >
+ // ... else, use the deduced tag
+ , ::boost::mp11::mp_at_c<_deduced_data,0>
+ >
+ >;
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ // If this parameter is explicitly tagged ...
+ typedef typename ::boost::mpl::eval_if<
+ _is_tagged
+ // ... just use it
+ , ::boost::mpl::identity<_arg_type>
+ // ... else ...
+ , ::boost::mpl::eval_if<
+ // if positional matching is turned on ...
+ _is_positional
+ // ... tag it positionally
+ , ::boost::mpl::apply_wrap2<TagFn,_tag,_argument>
+ // ... else, use the deduced tag
+ , ::boost::mpl::first<_deduced_data>
+ >
+ >::type _tagged;
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+ // Build the arg_list incrementally, prepending new nodes.
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using _error = ::boost::mp11::mp_if<
+ ::boost::mp11::mp_if<
+ ::std::is_same<Error,::boost::parameter::void_>
+ , ::std::is_same<_tagged,::boost::parameter::void_>
+ , ::boost::mp11::mp_false
+ >
+#else
+ typedef typename ::boost::mpl::if_<
+ typename ::boost::mpl::if_<
+ ::boost::is_same<Error,::boost::parameter::void_>
+ , ::boost::is_same<_tagged,::boost::parameter::void_>
+ , ::boost::mpl::false_
+ >::type
+#endif
+ , ::boost::parameter::aux::unmatched_argument<_argument>
+ , ::boost::parameter::void_
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >;
+#else
+ >::type _error;
+#endif
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using _argument_pack = typename ::boost::mp11::mp_if<
+ ::std::is_same<_tagged,::boost::parameter::void_>
+ , ::boost::mp11::mp_identity<ArgumentPack>
+ , ::boost::parameter::aux
+ ::append_to_make_arg_list<ArgumentPack,_tagged,EmitsErrors>
+ >::type;
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typedef typename ::boost::mpl::if_<
+ ::boost::is_same<_tagged,::boost::parameter::void_>
+ , ArgumentPack
+#if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+ , ::boost::parameter::aux::arg_list<_tagged,ArgumentPack>
+#else
+ , ::boost::parameter::aux
+ ::arg_list<_tagged,ArgumentPack,EmitsErrors>
+#endif
+ >::type _argument_pack;
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+ public:
+ typedef typename ::boost::parameter::aux::make_arg_list_aux<
+ typename List::tail
+ , DeducedArgs
+ , TagFn
+ , _is_positional
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ , ::boost::mp11::mp_at_c<_deduced_data,1>
+#else
+ , typename _deduced_data::second
+#endif
+ , _argument_pack
+ , _error
+ , EmitsErrors
+ >::type type;
+ };
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ template <
+ typename List
+ , typename DeducedArgs
+ , typename TagFn
+ , typename IsPositional
+ , typename UsedArgs
+ , typename ArgumentPack
+ , typename Error
+ , typename EmitsErrors
+ >
+ struct make_arg_list0
+ {
+ typedef typename ::boost::mpl::eval_if<
+ typename List::is_arg_const
+ , ::boost::parameter::aux::make_arg_list00<
+ List
+ , DeducedArgs
+ , TagFn
+ , IsPositional
+ , UsedArgs
+ , ArgumentPack
+ , typename List::arg const
+ , Error
+ , EmitsErrors
+ >
+ , ::boost::parameter::aux::make_arg_list00<
+ List
+ , DeducedArgs
+ , TagFn
+ , IsPositional
+ , UsedArgs
+ , ArgumentPack
+ , typename List::arg
+ , Error
+ , EmitsErrors
+ >
+ >::type type;
+ };
+#endif // Borland workarounds needed.
+
+ // Returns an ArgumentPack where the list of arguments has been tagged
+ // with keyword tags.
+ //
+ // List: A specialization of item<> (see below). Contains both
+ // the ordered ParameterSpecs, and the given arguments.
+ //
+ // DeducedArgs: A specialization of deduced_item<> (see below).
+ // A list containing only the deduced ParameterSpecs.
+ //
+ // TagFn: A metafunction class used to tag positional or deduced
+ // arguments with a keyword tag.
+ //
+ // IsPositional: An mpl::bool_<> specialization indicating if positional
+ // matching is to be performed.
+ //
+ // DeducedSet: An mpl::set<> containing the keyword tags used so far.
+ //
+ // ArgumentPack: The ArgumentPack built so far. This is initially an
+ // empty_arg_list and is built incrementally.
+ template <
+ typename List
+ , typename DeducedArgs
+ , typename TagFn
+ , typename IsPositional
+ , typename DeducedSet
+ , typename ArgumentPack
+ , typename Error
+ , typename EmitsErrors
+ >
+ struct make_arg_list_aux
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_if<
+ ::std::is_same<List,::boost::parameter::void_>
+ , ::boost::mp11::mp_identity<
+ ::boost::mp11::mp_list<ArgumentPack,Error>
+ >
+#else
+ : ::boost::mpl::eval_if<
+ ::boost::is_same<List,::boost::parameter::void_>
+ , ::boost::mpl::identity< ::boost::mpl::pair<ArgumentPack,Error> >
+#endif
+ , ::boost::parameter::aux::make_arg_list0<
+ List
+ , DeducedArgs
+ , TagFn
+ , IsPositional
+ , DeducedSet
+ , ArgumentPack
+ , Error
+ , EmitsErrors
+ >
+ >
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/set.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // VC6.5 was choking on the default parameters for make_arg_list_aux,
+ // so this just forwards to that adding in the defaults.
+ template <
+ typename List
+ , typename DeducedArgs
+ , typename TagFn
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ , typename EmitsErrors = ::boost::mp11::mp_true
+#else
+ , typename EmitsErrors = ::boost::mpl::true_
+#endif
+ >
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using make_arg_list = ::boost::parameter::aux::make_arg_list_aux<
+#else
+ struct make_arg_list
+ : ::boost::parameter::aux::make_arg_list_aux<
+#endif
+ List
+ , DeducedArgs
+ , TagFn
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ , ::boost::mp11::mp_true
+#else
+ , ::boost::mpl::true_
+#endif
+ , ::boost::parameter::aux::set0
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ , ::boost::parameter::aux::flat_like_arg_list<>
+#else
+ , ::boost::parameter::aux::empty_arg_list
+#endif
+ , ::boost::parameter::void_
+ , EmitsErrors
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >;
+#else
+ >
+ {
+ };
+#endif
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/make_deduced_items.hpp b/boost/parameter/aux_/pack/make_deduced_items.hpp
new file mode 100644
index 0000000000..3bc34332f0
--- /dev/null
+++ b/boost/parameter/aux_/pack/make_deduced_items.hpp
@@ -0,0 +1,53 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_MAKE_DEDUCED_ITEMS_HPP
+#define BOOST_PARAMETER_AUX_PACK_MAKE_DEDUCED_ITEMS_HPP
+
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/parameter/aux_/pack/deduced_item.hpp>
+#include <boost/parameter/deduced.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#else
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/type_traits/is_same.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Spec, typename Tail>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using make_deduced_items = ::boost::mp11::mp_if<
+ ::std::is_same<Spec,::boost::parameter::void_>
+ , ::boost::mp11::mp_identity< ::boost::parameter::void_>
+ , ::boost::mp11::mp_if<
+ ::boost::parameter::aux::is_deduced<Spec>
+ , ::boost::parameter::aux::make_deduced_item<Spec,Tail>
+ , Tail
+ >
+ >;
+#else
+ struct make_deduced_items
+ : ::boost::mpl::eval_if<
+ ::boost::is_same<Spec,::boost::parameter::void_>
+ , ::boost::mpl::identity< ::boost::parameter::void_>
+ , ::boost::mpl::eval_if<
+ ::boost::parameter::aux::is_deduced<Spec>
+ , ::boost::parameter::aux::make_deduced_item<Spec,Tail>
+ , Tail
+ >
+ >
+ {
+ };
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/make_items.hpp b/boost/parameter/aux_/pack/make_items.hpp
new file mode 100644
index 0000000000..ec1554bc64
--- /dev/null
+++ b/boost/parameter/aux_/pack/make_items.hpp
@@ -0,0 +1,45 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_MAKE_ITEMS_HPP
+#define BOOST_PARAMETER_AUX_PACK_MAKE_ITEMS_HPP
+
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/parameter/aux_/pack/item.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#else
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/type_traits/is_same.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Creates a item typelist.
+ template <typename Spec, typename Arg, typename Tail>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using make_items = ::boost::mp11::mp_if<
+ ::std::is_same<Arg,::boost::parameter::void_>
+ , ::boost::mp11::mp_identity< ::boost::parameter::void_>
+ , ::boost::parameter::aux::make_item<Spec,Arg,Tail>
+ >;
+#else
+ struct make_items
+ : ::boost::mpl::eval_if<
+ ::boost::is_same<Arg,::boost::parameter::void_>
+ , ::boost::mpl::identity< ::boost::parameter::void_>
+ , ::boost::parameter::aux::make_item<Spec,Arg,Tail>
+ >
+ {
+ };
+#endif
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/make_parameter_spec_items.hpp b/boost/parameter/aux_/pack/make_parameter_spec_items.hpp
new file mode 100644
index 0000000000..f13c4b5c16
--- /dev/null
+++ b/boost/parameter/aux_/pack/make_parameter_spec_items.hpp
@@ -0,0 +1,244 @@
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PACK_MAKE_PARAMETER_SPEC_ITEMS_HPP
+#define BOOST_PARAMETER_AUX_PACK_MAKE_PARAMETER_SPEC_ITEMS_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ // This recursive metafunction forwards successive elements of
+ // parameters::parameter_spec to make_deduced_items<>.
+ // -- Cromwell D. Enage
+ template <typename SpecSeq>
+ struct make_deduced_list;
+
+ // Helper for match_parameters_base_cond<...>, below.
+ template <typename ArgumentPackAndError, typename SpecSeq>
+ struct match_parameters_base_cond_helper;
+
+ // Helper metafunction for make_parameter_spec_items<...>, below.
+ template <typename SpecSeq, typename ...Args>
+ struct make_parameter_spec_items_helper;
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/void.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename SpecSeq>
+ struct make_parameter_spec_items_helper<SpecSeq>
+ {
+ typedef ::boost::parameter::void_ type;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/pack/make_deduced_items.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/list.hpp>
+#else
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/pop_front.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename SpecSeq>
+ struct make_deduced_list_not_empty
+ : ::boost::parameter::aux::make_deduced_items<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_front<SpecSeq>
+#else
+ typename ::boost::mpl::front<SpecSeq>::type
+#endif
+ , ::boost::parameter::aux::make_deduced_list<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_pop_front<SpecSeq>
+#else
+ typename ::boost::mpl::pop_front<SpecSeq>::type
+#endif
+ >
+ >
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/utility.hpp>
+#else
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/empty.hpp>
+#include <boost/mpl/identity.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename SpecSeq>
+ struct make_deduced_list
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_if<
+ ::boost::mp11::mp_empty<SpecSeq>
+ , ::boost::mp11::mp_identity< ::boost::parameter::void_>
+#else
+ : ::boost::mpl::eval_if<
+ ::boost::mpl::empty<SpecSeq>
+ , ::boost::mpl::identity< ::boost::parameter::void_>
+#endif
+ , ::boost::parameter::aux::make_deduced_list_not_empty<SpecSeq>
+ >
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <type_traits>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/pair.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename ArgumentPackAndError>
+ struct is_arg_pack_error_void
+ : ::boost::mpl::if_<
+ ::boost::is_same<
+ typename ::boost::mpl::second<ArgumentPackAndError>::type
+ , ::boost::parameter::void_
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >::type
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Checks if the arguments match the criteria of overload resolution.
+ // If NamedList satisfies the PS0, PS1, ..., this is a metafunction
+ // returning parameters. Otherwise it has no nested ::type.
+ template <typename ArgumentPackAndError, typename SpecSeq>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using match_parameters_base_cond = ::boost::mp11::mp_if<
+ ::boost::mp11::mp_empty<SpecSeq>
+ , ::std::is_same<
+ ::boost::mp11::mp_at_c<ArgumentPackAndError,1>
+ , ::boost::parameter::void_
+ >
+ , ::boost::parameter::aux::match_parameters_base_cond_helper<
+ ArgumentPackAndError
+ , SpecSeq
+ >
+ >;
+#else
+ struct match_parameters_base_cond
+ : ::boost::mpl::eval_if<
+ ::boost::mpl::empty<SpecSeq>
+ , ::boost::parameter::aux
+ ::is_arg_pack_error_void<ArgumentPackAndError>
+ , ::boost::parameter::aux::match_parameters_base_cond_helper<
+ ArgumentPackAndError
+ , SpecSeq
+ >
+ >
+ {
+ };
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/pack/satisfies.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename ArgumentPackAndError, typename SpecSeq>
+ struct match_parameters_base_cond_helper
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_if<
+#else
+ : ::boost::mpl::eval_if<
+#endif
+ ::boost::parameter::aux::satisfies_requirements_of<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_at_c<ArgumentPackAndError,0>
+ , ::boost::mp11::mp_front<SpecSeq>
+#else
+ typename ::boost::mpl::first<ArgumentPackAndError>::type
+ , typename ::boost::mpl::front<SpecSeq>::type
+#endif
+ >
+ , ::boost::parameter::aux::match_parameters_base_cond<
+ ArgumentPackAndError
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ , ::boost::mp11::mp_pop_front<SpecSeq>
+#else
+ , typename ::boost::mpl::pop_front<SpecSeq>::type
+#endif
+ >
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ , ::boost::mp11::mp_false
+#else
+ , ::boost::mpl::false_
+#endif
+ >
+ {
+ };
+
+ // This parameters item chaining metafunction class does not require
+ // the lengths of the SpecSeq and of Args parameter pack to match.
+ // Used by argument_pack to build the items in the resulting arg_list.
+ // -- Cromwell D. Enage
+ template <typename SpecSeq, typename ...Args>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using make_parameter_spec_items = ::boost::mp11::mp_if<
+ ::boost::mp11::mp_empty<SpecSeq>
+ , ::boost::mp11::mp_identity< ::boost::parameter::void_>
+ , ::boost::parameter::aux
+ ::make_parameter_spec_items_helper<SpecSeq,Args...>
+ >;
+#else
+ struct make_parameter_spec_items
+ : ::boost::mpl::eval_if<
+ ::boost::mpl::empty<SpecSeq>
+ , ::boost::mpl::identity< ::boost::parameter::void_>
+ , ::boost::parameter::aux
+ ::make_parameter_spec_items_helper<SpecSeq,Args...>
+ >
+ {
+ };
+#endif
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/pack/make_items.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename SpecSeq, typename A0, typename ...Args>
+ struct make_parameter_spec_items_helper<SpecSeq,A0,Args...>
+ : ::boost::parameter::aux::make_items<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_front<SpecSeq>
+#else
+ typename ::boost::mpl::front<SpecSeq>::type
+#endif
+ , A0
+ , ::boost::parameter::aux::make_parameter_spec_items<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_pop_front<SpecSeq>
+#else
+ typename ::boost::mpl::pop_front<SpecSeq>::type
+#endif
+ , Args...
+ >
+ >
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/parameter_requirements.hpp b/boost/parameter/aux_/pack/parameter_requirements.hpp
new file mode 100644
index 0000000000..709da2108b
--- /dev/null
+++ b/boost/parameter/aux_/pack/parameter_requirements.hpp
@@ -0,0 +1,25 @@
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_PARAMETER_REQUIREMENTS_HPP
+#define BOOST_PARAMETER_AUX_PACK_PARAMETER_REQUIREMENTS_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Used to pass static information about parameter requirements through
+ // the satisfies() overload set (below). The matched function is never
+ // invoked, but its type indicates whether a parameter matches at
+ // compile-time.
+ template <typename Keyword, typename Predicate, typename HasDefault>
+ struct parameter_requirements
+ {
+ typedef Keyword keyword;
+ typedef Predicate predicate;
+ typedef HasDefault has_default;
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/predicate.hpp b/boost/parameter/aux_/pack/predicate.hpp
new file mode 100644
index 0000000000..752664c60b
--- /dev/null
+++ b/boost/parameter/aux_/pack/predicate.hpp
@@ -0,0 +1,87 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_PREDICATE_HPP
+#define BOOST_PARAMETER_AUX_PACK_PREDICATE_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ // helper for get_predicate<...>, below
+ template <typename T>
+ struct get_predicate_or_default
+ {
+ typedef T type;
+ };
+
+ // helper for predicate<...>, below
+ template <typename T>
+ struct get_predicate
+ : ::boost::parameter::aux
+ ::get_predicate_or_default<typename T::predicate>
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/use_default.hpp>
+#include <boost/parameter/aux_/always_true_predicate.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <>
+ struct get_predicate_or_default< ::boost::parameter::aux::use_default>
+ {
+ typedef ::boost::parameter::aux::always_true_predicate type;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/required.hpp>
+#include <boost/parameter/optional.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using predicate = ::boost::mp11::mp_if<
+ ::boost::mp11::mp_if<
+ ::boost::parameter::aux::is_optional<T>
+ , ::boost::mp11::mp_true
+ , ::boost::parameter::aux::is_required<T>
+ >
+ , ::boost::parameter::aux::get_predicate<T>
+ , ::boost::mp11::mp_identity<
+ ::boost::parameter::aux::always_true_predicate
+ >
+ >;
+#else
+ struct predicate
+ : ::boost::mpl::eval_if<
+ typename ::boost::mpl::if_<
+ ::boost::parameter::aux::is_optional<T>
+ , ::boost::mpl::true_
+ , ::boost::parameter::aux::is_required<T>
+ >::type
+ , ::boost::parameter::aux::get_predicate<T>
+ , ::boost::mpl::identity<
+ ::boost::parameter::aux::always_true_predicate
+ >
+ >
+ {
+ };
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/satisfies.hpp b/boost/parameter/aux_/pack/satisfies.hpp
new file mode 100644
index 0000000000..90c8d21e58
--- /dev/null
+++ b/boost/parameter/aux_/pack/satisfies.hpp
@@ -0,0 +1,142 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_SATISFIES_HPP
+#define BOOST_PARAMETER_AUX_PACK_SATISFIES_HPP
+
+#include <boost/parameter/config.hpp>
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#include <boost/parameter/aux_/arg_list.hpp>
+#include <boost/parameter/aux_/augment_predicate.hpp>
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/type_traits/is_same.hpp>
+#else // !BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#else
+#include <boost/mpl/bool.hpp>
+#endif
+#include <boost/parameter/aux_/yesno.hpp>
+#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
+#endif // MSVC-7.1 workarounds needed
+
+namespace boost { namespace parameter { namespace aux {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+ template <typename ArgList, typename ParameterRequirements, typename Bound>
+ struct satisfies_impl
+ : ::boost::parameter::aux::augment_predicate<
+ typename ParameterRequirements::predicate
+ , typename ArgList::reference
+ , typename ArgList::key_type
+ , Bound
+ , ArgList
+ >
+ {
+ };
+#endif
+
+ // Returns mpl::true_ iff the given ParameterRequirements are satisfied by
+ // ArgList.
+ template <typename ArgList, typename ParameterRequirements>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using satisfies = ::boost::mp11::mp_bool<
+ sizeof(
+ ::boost::parameter::aux::to_yesno(
+ ArgList::satisfies(
+ static_cast<ParameterRequirements*>(
+ BOOST_PARAMETER_AUX_PP_NULLPTR
+ )
+ , static_cast<ArgList*>(BOOST_PARAMETER_AUX_PP_NULLPTR)
+ )
+ )
+ ) == sizeof(::boost::parameter::aux::yes_tag)
+ >;
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ class satisfies
+ {
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+ // VC7.1 can't handle the sizeof() implementation below,
+ // so we use this instead.
+ typedef typename ::boost::mpl::apply_wrap3<
+ typename ArgList::binding
+ , typename ParameterRequirements::keyword
+ , ::boost::parameter::void_
+ , ::boost::mpl::false_
+ >::type _bound;
+
+ public:
+ typedef typename ::boost::mpl::eval_if<
+ ::boost::is_same<_bound,::boost::parameter::void_>
+ , typename ParameterRequirements::has_default
+ , ::boost::mpl::eval_if<
+ ::boost::is_same<
+ ArgList
+ , ::boost::parameter::aux::empty_arg_list
+ >
+ , ::boost::mpl::false_
+ , ::boost::parameter::aux::satisfies_impl<
+ ArgList
+ , ParameterRequirements
+ , _bound
+ >
+ >
+ >::type type;
+#else // !BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+ BOOST_STATIC_CONSTANT(
+ bool, _value = (
+ sizeof(
+ ::boost::parameter::aux::to_yesno(
+ ArgList::satisfies(
+ static_cast<ParameterRequirements*>(
+ BOOST_PARAMETER_AUX_PP_NULLPTR
+ )
+ , static_cast<ArgList*>(BOOST_PARAMETER_AUX_PP_NULLPTR)
+ )
+ )
+ ) == sizeof(::boost::parameter::aux::yes_tag)
+ )
+ );
+
+ public:
+ typedef ::boost::mpl::bool_<
+ ::boost::parameter::aux
+ ::satisfies<ArgList,ParameterRequirements>::_value
+ > type;
+#endif // MSVC-7.1 workarounds needed
+ };
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/pack/as_parameter_requirements.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Returns mpl::true_ if the requirements of the given ParameterSpec
+ // are satisfied by ArgList.
+ template <typename ArgList, typename ParameterSpec>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using satisfies_requirements_of = ::boost::parameter::aux::satisfies<
+ ArgList
+ , typename ::boost::parameter::aux
+ ::as_parameter_requirements<ParameterSpec>::type
+ >;
+#else
+ struct satisfies_requirements_of
+ : ::boost::parameter::aux::satisfies<
+ ArgList
+ , typename ::boost::parameter::aux
+ ::as_parameter_requirements<ParameterSpec>::type
+ >::type
+ {
+ };
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/tag_deduced.hpp b/boost/parameter/aux_/pack/tag_deduced.hpp
new file mode 100644
index 0000000000..9065ab9558
--- /dev/null
+++ b/boost/parameter/aux_/pack/tag_deduced.hpp
@@ -0,0 +1,59 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_TAG_DEDUCED_HPP
+#define BOOST_PARAMETER_AUX_PACK_TAG_DEDUCED_HPP
+
+#include <boost/parameter/aux_/set.hpp>
+#include <boost/parameter/aux_/pack/tag_type.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+#else
+#include <boost/mpl/pair.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Tags a deduced argument Arg with the keyword tag of Spec using TagFn.
+ // Returns the tagged argument and the mpl::set<> UsedArgs with the
+ // tag of Spec inserted.
+ template <typename UsedArgs, typename Spec, typename Arg, typename TagFn>
+ struct tag_deduced
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_list<
+ ::boost::mp11::mp_apply_q<
+ TagFn
+ , ::boost::mp11::mp_list<
+ typename ::boost::parameter::aux::tag_type<Spec>::type
+ , Arg
+ >
+ >
+#else
+ typedef ::boost::mpl::pair<
+ typename ::boost::mpl::apply_wrap2<
+ TagFn
+ , typename ::boost::parameter::aux::tag_type<Spec>::type
+ , Arg
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , typename ::boost::parameter::aux::insert_<
+ UsedArgs
+ , typename ::boost::parameter::aux::tag_type<Spec>::type
+ >::type
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >;
+#else
+ > type;
+#endif
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/tag_keyword_arg.hpp b/boost/parameter/aux_/pack/tag_keyword_arg.hpp
new file mode 100644
index 0000000000..ae4154e3fd
--- /dev/null
+++ b/boost/parameter/aux_/pack/tag_keyword_arg.hpp
@@ -0,0 +1,30 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_TAG_KEYWORD_ARG_HPP
+#define BOOST_PARAMETER_AUX_PACK_TAG_KEYWORD_ARG_HPP
+
+#include <boost/parameter/aux_/tag.hpp>
+#include <boost/parameter/config.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ struct tag_keyword_arg
+ {
+ template <typename K, typename T>
+ struct apply
+ {
+ typedef typename ::boost::parameter::aux::tag<K,T>::type type;
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename K, typename T>
+ using fn = typename ::boost::parameter::aux::tag<K,T>::type;
+#endif
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/tag_keyword_arg_ref.hpp b/boost/parameter/aux_/pack/tag_keyword_arg_ref.hpp
new file mode 100644
index 0000000000..4d67975ddc
--- /dev/null
+++ b/boost/parameter/aux_/pack/tag_keyword_arg_ref.hpp
@@ -0,0 +1,67 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_TAG_KEYWORD_ARG_REF_HPP
+#define BOOST_PARAMETER_AUX_PACK_TAG_KEYWORD_ARG_REF_HPP
+
+#include <boost/parameter/aux_/unwrap_cv_reference.hpp>
+#include <boost/parameter/aux_/tagged_argument.hpp>
+#include <boost/parameter/config.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <
+ typename Keyword
+ , typename ActualArg
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ , typename = typename ::boost::parameter::aux
+ ::is_cv_reference_wrapper<ActualArg>::type
+#endif
+ >
+ struct tag_ref
+ {
+ typedef ::boost::parameter::aux::tagged_argument<
+ Keyword
+ , typename ::boost::parameter::aux
+ ::unwrap_cv_reference<ActualArg>::type
+ > type;
+ };
+}}} // namespace boost::parameter::aux_
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+
+#include <boost/mpl/bool.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Keyword, typename ActualArg>
+ struct tag_ref<Keyword,ActualArg,::boost::mpl::false_>
+ {
+ typedef ::boost::parameter::aux
+ ::tagged_argument<Keyword,ActualArg> type;
+ };
+}}} // namespace boost::parameter::aux_
+
+#endif // Borland workarounds needed.
+
+namespace boost { namespace parameter { namespace aux {
+
+ struct tag_keyword_arg_ref
+ {
+ template <typename K, typename T>
+ struct apply
+ {
+ typedef typename ::boost::parameter::aux::tag_ref<K,T>::type type;
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename K, typename T>
+ using fn = typename ::boost::parameter::aux::tag_ref<K,T>::type;
+#endif
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/tag_template_keyword_arg.hpp b/boost/parameter/aux_/pack/tag_template_keyword_arg.hpp
new file mode 100644
index 0000000000..849966edb9
--- /dev/null
+++ b/boost/parameter/aux_/pack/tag_template_keyword_arg.hpp
@@ -0,0 +1,30 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_TAG_TEMPLATE_KEYWORD_ARG_HPP
+#define BOOST_PARAMETER_AUX_PACK_TAG_TEMPLATE_KEYWORD_ARG_HPP
+
+#include <boost/parameter/template_keyword.hpp>
+#include <boost/parameter/config.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ struct tag_template_keyword_arg
+ {
+ template <typename K, typename T>
+ struct apply
+ {
+ typedef ::boost::parameter::template_keyword<K,T> type;
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename K, typename T>
+ using fn = ::boost::parameter::template_keyword<K,T>;
+#endif
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/tag_type.hpp b/boost/parameter/aux_/pack/tag_type.hpp
new file mode 100644
index 0000000000..81d1a1476f
--- /dev/null
+++ b/boost/parameter/aux_/pack/tag_type.hpp
@@ -0,0 +1,89 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_TAG_TYPE_HPP
+#define BOOST_PARAMETER_AUX_PACK_TAG_TYPE_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ // helper for tag_type<...>, below.
+ template <typename T>
+ struct get_tag_type0
+ {
+ typedef typename T::key_type type;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/deduced.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/utility.hpp>
+#else
+#include <boost/mpl/eval_if.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ struct get_tag_type
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_if<
+#else
+ : ::boost::mpl::eval_if<
+#endif
+ ::boost::parameter::aux::is_deduced0<T>
+ , ::boost::parameter::aux::get_tag_type0<typename T::key_type>
+ , ::boost::parameter::aux::get_tag_type0<T>
+ >
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/required.hpp>
+#include <boost/parameter/optional.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ using tag_type = ::boost::mp11::mp_if<
+ ::boost::mp11::mp_if<
+ ::boost::parameter::aux::is_optional<T>
+ , ::boost::mp11::mp_true
+ , ::boost::parameter::aux::is_required<T>
+ >
+ , ::boost::parameter::aux::get_tag_type<T>
+ , ::boost::mp11::mp_identity<T>
+ >;
+}}} // namespace boost::parameter::aux
+
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/identity.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ struct tag_type
+ : ::boost::mpl::eval_if<
+ typename ::boost::mpl::if_<
+ ::boost::parameter::aux::is_optional<T>
+ , ::boost::mpl::true_
+ , ::boost::parameter::aux::is_required<T>
+ >::type
+ , ::boost::parameter::aux::get_tag_type<T>
+ , ::boost::mpl::identity<T>
+ >
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pack/unmatched_argument.hpp b/boost/parameter/aux_/pack/unmatched_argument.hpp
new file mode 100644
index 0000000000..72a1bc5f62
--- /dev/null
+++ b/boost/parameter/aux_/pack/unmatched_argument.hpp
@@ -0,0 +1,41 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PACK_UNMATCHED_ARGUMENT_HPP
+#define BOOST_PARAMETER_AUX_PACK_UNMATCHED_ARGUMENT_HPP
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <type_traits>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ struct unmatched_argument
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ static_assert(::std::is_same<T,void>::value, "T == void");
+#else
+ BOOST_MPL_ASSERT((
+ typename ::boost::mpl::if_<
+ ::boost::is_same<T,void>
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >::type
+ ));
+#endif
+ typedef int type;
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/parameter_requirements.hpp b/boost/parameter/aux_/parameter_requirements.hpp
index ad7a129dd7..d372691e50 100644
--- a/boost/parameter/aux_/parameter_requirements.hpp
+++ b/boost/parameter/aux_/parameter_requirements.hpp
@@ -1,25 +1,12 @@
-// Copyright Daniel Wallin, David Abrahams 2005. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef PARAMETER_REQUIREMENTS_050331_HPP
#define PARAMETER_REQUIREMENTS_050331_HPP
-namespace boost { namespace parameter { namespace aux {
+#include <boost/parameter/aux_/pack/parameter_requirements.hpp>
-// Used to pass static information about parameter requirements
-// through the satisfies() overload set (below). The
-// matched function is never invoked, but its type indicates whether
-// a parameter matches at compile-time
-template <class Keyword, class Predicate, class HasDefault>
-struct parameter_requirements
-{
- typedef Keyword keyword;
- typedef Predicate predicate;
- typedef HasDefault has_default;
-};
+#endif // include guard
-}}} // namespace boost::parameter::aux
-
-#endif // PARAMETER_REQUIREMENTS_050331_HPP
diff --git a/boost/parameter/aux_/parenthesized_type.hpp b/boost/parameter/aux_/parenthesized_type.hpp
index 69e7a237d4..863e062e90 100644
--- a/boost/parameter/aux_/parenthesized_type.hpp
+++ b/boost/parameter/aux_/parenthesized_type.hpp
@@ -1,35 +1,12 @@
-// Copyright David Abrahams 2006. Distributed under the Boost
-// Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_PARAMETER_AUX_PARENTHESIZED_TYPE_DWA2006414_HPP
-# define BOOST_PARAMETER_AUX_PARENTHESIZED_TYPE_DWA2006414_HPP
-
-# include <boost/config.hpp>
-# include <boost/detail/workaround.hpp>
-
-namespace boost { namespace parameter { namespace aux {
+// Copyright David Abrahams 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
-// A macro that takes a parenthesized C++ type name (T) and transforms
-// it into an un-parenthesized type expression equivalent to T.
-# define BOOST_PARAMETER_PARENTHESIZED_TYPE(x) \
- boost::parameter::aux::unaryfunptr_arg_type< void(*)x >::type
-
-// A metafunction that transforms void(*)(T) -> T
-template <class UnaryFunctionPointer>
-struct unaryfunptr_arg_type;
+#ifndef BOOST_PARAMETER_AUX_PARENTHESIZED_TYPE_DWA2006414_HPP
+#define BOOST_PARAMETER_AUX_PARENTHESIZED_TYPE_DWA2006414_HPP
-template <class Arg>
-struct unaryfunptr_arg_type<void(*)(Arg)>
-{
- typedef Arg type;
-};
+#include <boost/parameter/aux_/preprocessor/impl/parenthesized_type.hpp>
-template <>
-struct unaryfunptr_arg_type<void(*)(void)>
-{
- typedef void type;
-};
-
-}}} // namespace boost::parameter::aux
+#endif // include guard
-#endif // BOOST_PARAMETER_AUX_PARENTHESIZED_TYPE_DWA2006414_HPP
diff --git a/boost/parameter/aux_/pp_impl/argument_pack.hpp b/boost/parameter/aux_/pp_impl/argument_pack.hpp
new file mode 100644
index 0000000000..85bf13f744
--- /dev/null
+++ b/boost/parameter/aux_/pp_impl/argument_pack.hpp
@@ -0,0 +1,91 @@
+// Copyright Daniel Wallin 2006.
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PP_IMPL_ARGUMENT_PACK_HPP
+#define BOOST_PARAMETER_AUX_PP_IMPL_ARGUMENT_PACK_HPP
+
+#include <boost/parameter/aux_/pack/tag_keyword_arg.hpp>
+#include <boost/parameter/aux_/pack/make_arg_list.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#include <boost/parameter/aux_/pack/make_parameter_spec_items.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/list.hpp>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/pair.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Parameters, typename ...Args>
+ struct argument_pack
+ {
+ typedef typename ::boost::parameter::aux::make_arg_list<
+ typename ::boost::parameter::aux::make_parameter_spec_items<
+ typename Parameters::parameter_spec
+ , Args...
+ >::type
+ , typename Parameters::deduced_list
+ , ::boost::parameter::aux::tag_keyword_arg
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ , ::boost::mp11::mp_false
+#else
+ , ::boost::mpl::false_
+#endif
+ >::type result;
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_at_c<result,0>;
+#else
+ typedef typename ::boost::mpl::first<result>::type type;
+#endif
+ };
+}}} // namespace boost::parameter::aux
+
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/parameter/aux_/pack/make_items.hpp>
+#include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_begin.hpp>
+#include <boost/preprocessor/facilities/intercept.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/pair.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <
+ typename Parameters
+ BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
+ BOOST_PARAMETER_MAX_ARITY
+ , typename A
+ , = ::boost::parameter::void_ BOOST_PP_INTERCEPT
+ )
+ >
+ struct argument_pack
+ {
+ typedef typename ::boost::parameter::aux::make_arg_list<
+ typename BOOST_PARAMETER_build_arg_list(
+ BOOST_PARAMETER_MAX_ARITY
+ , ::boost::parameter::aux::make_items
+ , typename Parameters::parameter_spec
+ , A
+ )::type
+ , typename Parameters::deduced_list
+ , ::boost::parameter::aux::tag_keyword_arg
+ , ::boost::mpl::false_
+ >::type result;
+ typedef typename ::boost::mpl::first<result>::type type;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_end.hpp>
+
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pp_impl/match.hpp b/boost/parameter/aux_/pp_impl/match.hpp
new file mode 100644
index 0000000000..a903975de6
--- /dev/null
+++ b/boost/parameter/aux_/pp_impl/match.hpp
@@ -0,0 +1,55 @@
+// Copyright Daniel Wallin 2006.
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PP_IMPL_MATCH_HPP
+#define BOOST_PARAMETER_AUX_PP_IMPL_MATCH_HPP
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Recast the ParameterSpec's nested match metafunction
+ // as a free metafunction.
+ //
+ // No more limits set by BOOST_PARAMETER_MAX_ARITY. -- Cromwell D. Enage
+ template <typename Parameters, typename ...Args>
+ struct match : Parameters::BOOST_NESTED_TEMPLATE match<Args...>
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#else
+
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/preprocessor/facilities/intercept.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Recast the ParameterSpec's nested match metafunction
+ // as a free metafunction.
+ template <
+ typename Parameters
+ BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
+ BOOST_PARAMETER_MAX_ARITY
+ , typename A
+ , = ::boost::parameter::void_ BOOST_PP_INTERCEPT
+ )
+ >
+ struct match
+ : Parameters::BOOST_NESTED_TEMPLATE match<
+ BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, A)
+ >
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+#endif // include guard
+
diff --git a/boost/parameter/aux_/pp_impl/unwrap_predicate.hpp b/boost/parameter/aux_/pp_impl/unwrap_predicate.hpp
new file mode 100644
index 0000000000..6141612575
--- /dev/null
+++ b/boost/parameter/aux_/pp_impl/unwrap_predicate.hpp
@@ -0,0 +1,97 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PP_IMPL_UNWRAP_PREDICATE_HPP
+#define BOOST_PARAMETER_AUX_PP_IMPL_UNWRAP_PREDICATE_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Given Match, which is "void x" where x is an argument matching
+ // criterion, extract a corresponding MPL predicate.
+ template <typename Match>
+ struct unwrap_predicate;
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/always_true_predicate.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Match anything
+ template <>
+ struct unwrap_predicate<void*>
+ {
+ typedef ::boost::parameter::aux::always_true_predicate type;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/config.hpp>
+
+#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580))
+#include <boost/parameter/aux_/void.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ // A matching predicate is explicitly specified.
+#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580))
+ template <typename Predicate>
+ struct unwrap_predicate< ::boost::parameter::aux::voidstar(Predicate)>
+ {
+ typedef Predicate type;
+ };
+#else
+ template <typename Predicate>
+ struct unwrap_predicate<void *(Predicate)>
+ {
+ typedef Predicate type;
+ };
+#endif // SunProCC workarounds needed.
+}}} // namespace boost::parameter::aux
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <type_traits>
+#else
+#include <boost/mpl/placeholders.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ // A type to which the argument is supposed to be convertible is
+ // specified.
+ template <typename Target>
+ struct unwrap_predicate<void (Target)>
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ struct type
+ {
+ template <typename Argument, typename ArgumentPack>
+ struct apply
+ : ::boost::mpl::if_<
+ ::std::is_convertible<Argument,Target>
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >
+ {
+ };
+
+ template <typename Argument, typename ArgumentPack>
+ using fn = ::std::is_convertible<Argument,Target>;
+ };
+#else
+ typedef ::boost::mpl::if_<
+ ::boost::is_convertible< ::boost::mpl::_,Target>
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ > type;
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/binary_seq_for_each.hpp b/boost/parameter/aux_/preprocessor/binary_seq_for_each.hpp
new file mode 100644
index 0000000000..700d918a9d
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/binary_seq_for_each.hpp
@@ -0,0 +1,1638 @@
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PREPROCESSOR_BINARY_SEQ_FOR_EACH_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_BINARY_SEQ_FOR_EACH_HPP
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_0(macro, data)
+/**/
+
+#include <boost/parameter/aux_/preprocessor/for_each_pred.hpp>
+#include <boost/parameter/aux_/preprocessor/binary_seq_for_each_inc.hpp>
+#include <boost/preprocessor/repetition/for.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_1(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_2 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_1_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_2(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_3 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_1_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_3(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_4 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_1_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_4(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_5 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_1_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_5(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_6 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_1_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_6(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_7 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_1_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_7(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_8 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_1_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_8(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_9 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_2_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_9 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_2_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_9(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_10 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_3_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_10 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_3_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_10 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_3_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_10 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_3_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_10(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_11 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_4_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_11 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_4_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_11 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_4_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_11 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_4_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_11 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_4_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_11 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_4_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_11 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_4_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_11 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_4_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_11(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_12(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_13(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N \
+ , macro \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_14(macro, data) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(0)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(1)(0)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(0)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(0)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(0)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(0)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(0)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(0)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(0)(1)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(0)(1)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(0)(1)(1)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ ) \
+ BOOST_PP_FOR( \
+ (data)(1)(1)(1)(1)(1)(1)(1)(0)(0)(0)(0)(0)(0)(0) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15 \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N \
+ , macro \
+ )
+/**/
+
+#include <boost/preprocessor/seq/elem.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH(n, seq) \
+ BOOST_PP_CAT(BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_, n)( \
+ BOOST_PP_SEQ_ELEM(0, seq), BOOST_PP_SEQ_ELEM(1, seq) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_Z(z, n, seq) \
+ BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH(n, seq)
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/binary_seq_for_each_inc.hpp b/boost/parameter/aux_/preprocessor/binary_seq_for_each_inc.hpp
new file mode 100644
index 0000000000..7e97546739
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/binary_seq_for_each_inc.hpp
@@ -0,0 +1,1796 @@
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PREPROCESSOR_BINARY_SEQ_FOR_EACH_INC_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_BINARY_SEQ_FOR_EACH_INC_HPP
+
+#include <boost/parameter/aux_/preprocessor/inc_binary_seq.hpp>
+#include <boost/preprocessor/seq/seq.hpp>
+#include <boost/preprocessor/seq/push_front.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_1_N(r, seq) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_TAIL(seq)) \
+ , BOOST_PP_SEQ_HEAD(seq) \
+ )
+/**/
+
+#include <boost/parameter/aux_/preprocessor/seq_merge.hpp>
+#include <boost/preprocessor/seq/first_n.hpp>
+#include <boost/preprocessor/seq/rest_n.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_2_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(2, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(2, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_3_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(3, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(3, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_4_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(4, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(4, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_5_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(5, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(5, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_6_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(6, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(6, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_7_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(7, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(7, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_8_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(8, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(8, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_9_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(9, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(9, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_10_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(10, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(10, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_11_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(11, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(11, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_12_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(12, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(12, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_13_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(13, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(13, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_14_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(14, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(14, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_15_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(15, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(15, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_16_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(16, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(16, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_17_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(17, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(17, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_18_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(18, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(18, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_19_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(19, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(19, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_20_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(20, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(20, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_21_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(21, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(21, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_22_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(22, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(22, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_23_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(23, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(23, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_24_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(24, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(24, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_25_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(25, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(25, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_26_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(26, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(26, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_27_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(27, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(27, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_28_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(28, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(28, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_29_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(29, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(29, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_30_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(30, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(30, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_31_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(31, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(31, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_32_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(32, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(32, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_33_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(33, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(33, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_34_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(34, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(34, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_35_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(35, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(35, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_36_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(36, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(36, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_37_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(37, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(37, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_38_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(38, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(38, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_39_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(39, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(39, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_40_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(40, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(40, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_41_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(41, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(41, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_42_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(42, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(42, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_43_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(43, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(43, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_44_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(44, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(44, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_45_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(45, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(45, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_46_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(46, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(46, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_47_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(47, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(47, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_48_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(48, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(48, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_49_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(49, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(49, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_50_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(50, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(50, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_51_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(51, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(51, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_52_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(52, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(52, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_53_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(53, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(53, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_54_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(54, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(54, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_55_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(55, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(55, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_56_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(56, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(56, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_57_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(57, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(57, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_58_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(58, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(58, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_59_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(59, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(59, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_60_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(60, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(60, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_61_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(61, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(61, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_62_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(62, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(62, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_63_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(63, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(63, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_64_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(64, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(64, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_65_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(65, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(65, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_66_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(66, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(66, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_67_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(67, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(67, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_68_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(68, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(68, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_69_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(69, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(69, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_70_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(70, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(70, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_71_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(71, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(71, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_72_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(72, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(72, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_73_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(73, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(73, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_74_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(74, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(74, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_75_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(75, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(75, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_76_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(76, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(76, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_77_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(77, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(77, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_78_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(78, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(78, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_79_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(79, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(79, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_80_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(80, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(80, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_81_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(81, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(81, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_82_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(82, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(82, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_83_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(83, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(83, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_84_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(84, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(84, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_85_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(85, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(85, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_86_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(86, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(86, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_87_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(87, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(87, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_88_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(88, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(88, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_89_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(89, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(89, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_90_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(90, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(90, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_91_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(91, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(91, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_92_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(92, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(92, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_93_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(93, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(93, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_94_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(94, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(94, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_95_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(95, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(95, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_96_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(96, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(96, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_97_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(97, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(97, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_98_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(98, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(98, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_99_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(99, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(99, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_100_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(100, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(100, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_101_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(101, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(101, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_102_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(102, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(102, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_103_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(103, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(103, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_104_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(104, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(104, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_105_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(105, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(105, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_106_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(106, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(106, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_107_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(107, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(107, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_108_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(108, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(108, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_109_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(109, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(109, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_110_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(110, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(110, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_111_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(111, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(111, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_112_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(112, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(112, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_113_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(113, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(113, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_114_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(114, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(114, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_115_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(115, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(115, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_116_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(116, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(116, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_117_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(117, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(117, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_118_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(118, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(118, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_119_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(119, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(119, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_120_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(120, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(120, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_121_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(121, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(121, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_122_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(122, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(122, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_123_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(123, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(123, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_124_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(124, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(124, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_125_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(125, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(125, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_126_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(126, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(126, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_127_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(127, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(127, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_128_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(128, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(128, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_129_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(129, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(129, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_130_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(130, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(130, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_131_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(131, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(131, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_132_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(132, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(132, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_133_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(133, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(133, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_134_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(134, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(134, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_135_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(135, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(135, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_136_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(136, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(136, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_137_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(137, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(137, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_138_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(138, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(138, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_139_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(139, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(139, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_140_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(140, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(140, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_141_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(11, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(141, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_142_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(142, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(142, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_143_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(143, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(143, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_144_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(144, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(144, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_145_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(145, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(145, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_146_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(146, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(146, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_147_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(147, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(147, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_148_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(148, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(148, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_149_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(149, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(149, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_150_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(150, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(150, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_151_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(151, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(151, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_152_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(152, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(152, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_153_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(153, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(153, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_154_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(154, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(154, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_155_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(155, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(155, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_156_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(156, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(156, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_157_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(157, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(157, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_158_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(158, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(158, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_159_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(159, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(159, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_160_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(160, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(160, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_161_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(161, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(161, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_162_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(162, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(162, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_163_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(163, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(163, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_164_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(164, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(164, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_165_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(165, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(165, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_166_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(166, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(166, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_167_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(167, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(167, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_168_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(168, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(168, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_169_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(169, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(169, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_170_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(170, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(170, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_171_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(171, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(171, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_172_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(172, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(172, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_173_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(173, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(173, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_174_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(174, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(174, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_175_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(175, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(175, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_176_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(176, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(176, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_177_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(177, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(177, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_178_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(178, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(178, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_179_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(179, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(179, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_180_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(180, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(180, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_181_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(181, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(181, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_182_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(182, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(182, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_183_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(183, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(183, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_184_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(184, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(184, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_185_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(185, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(185, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_186_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(186, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(186, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_187_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(187, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(187, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_188_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(188, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(188, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_189_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(189, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(189, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_190_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(190, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(190, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_191_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(191, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(191, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_192_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(192, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(192, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_193_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(193, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(193, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_194_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(194, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(194, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_195_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(195, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(195, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_196_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(196, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(196, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_197_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(197, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(197, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_198_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(198, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(198, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_199_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(199, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(199, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_200_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(200, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(200, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_201_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(201, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(201, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_202_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(202, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(202, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_203_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(203, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(203, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_204_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(204, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(204, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_205_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(205, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(205, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_206_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(206, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(206, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_207_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(207, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(207, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_208_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(208, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(208, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_209_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(209, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(209, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_210_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(210, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(210, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_211_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(211, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(211, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_212_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(212, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(212, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_213_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(213, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(213, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_214_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(214, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(214, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_215_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(215, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(215, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_216_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(216, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(216, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_217_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(217, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(217, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_218_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(218, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(218, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_219_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(219, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(219, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_220_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(220, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(220, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_221_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(221, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(221, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_222_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(222, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(222, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_223_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(223, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(223, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_224_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(224, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(224, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_225_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(225, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(225, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_226_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(226, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(226, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_227_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(227, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(227, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_228_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(228, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(228, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_229_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(229, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(229, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_230_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(230, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(230, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_231_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(231, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(231, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_232_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(232, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(232, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_233_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(233, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(233, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_234_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(234, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(234, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_235_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(235, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(235, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_236_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(236, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(236, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_237_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(237, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(237, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_238_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(238, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(238, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_239_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(239, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(239, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_240_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(240, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(240, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_241_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(241, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(241, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_242_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(242, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(242, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_243_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(243, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(243, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_244_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(244, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(244, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_245_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(245, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(245, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_246_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(246, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(246, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_247_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(247, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(247, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_248_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(248, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(248, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_249_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(249, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(249, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_250_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(250, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(250, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_251_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(251, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(251, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_252_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(252, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(252, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_253_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(253, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(253, seq)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_INC_254_N(r, seq) \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE( \
+ BOOST_PP_SEQ_FIRST_N(254, seq) \
+ , BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(BOOST_PP_SEQ_REST_N(254, seq)) \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/binary_seq_to_args.hpp b/boost/parameter/aux_/preprocessor/binary_seq_to_args.hpp
new file mode 100644
index 0000000000..4b4ca6290a
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/binary_seq_to_args.hpp
@@ -0,0 +1,65 @@
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PREPROCESSOR_BINARY_SEQ_TO_ARGS_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_BINARY_SEQ_TO_ARGS_HPP
+
+#include <boost/preprocessor/seq/elem.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_0_1(n, prefix_seq) \
+ BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, prefix_seq), n) const&
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_1_1(n, prefix_seq) \
+ BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, prefix_seq), n)&
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_0_2(n, prefix_seq) \
+ BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_0_1(n, prefix_seq) \
+ BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1, prefix_seq), n)
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_1_2(n, prefix_seq) \
+ BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_1_1(n, prefix_seq) \
+ BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1, prefix_seq), n)
+/**/
+
+#include <boost/preprocessor/seq/size.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_0(prefix_seq) \
+ BOOST_PP_CAT( \
+ BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_0_ \
+ , BOOST_PP_SEQ_SIZE(prefix_seq) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_1(prefix_seq) \
+ BOOST_PP_CAT( \
+ BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_1_ \
+ , BOOST_PP_SEQ_SIZE(prefix_seq) \
+ )
+/**/
+
+#include <boost/parameter/aux_/preprocessor/convert_binary_seq.hpp>
+
+// This macro converts the specified Boost.Preprocessor sequence of 1s and 0s
+// into a formal function parameter list.
+//
+// Example:
+// BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARGS((1)(0)(1)(0), (P)(p))
+// expands to
+// P0 & p0, P1 const& p1, P2 & p2, P3 const& p3
+#define BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARGS(binary_seq, prefix_seq) \
+ BOOST_PARAMETER_AUX_PP_CONVERT_BINARY_SEQ( \
+ binary_seq \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_0(prefix_seq) \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARG_1(prefix_seq) \
+ , prefix_seq \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/convert_binary_seq.hpp b/boost/parameter/aux_/preprocessor/convert_binary_seq.hpp
new file mode 100644
index 0000000000..64832b3d4b
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/convert_binary_seq.hpp
@@ -0,0 +1,57 @@
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PREPROCESSOR_CONVERT_BINARY_SEQ_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_CONVERT_BINARY_SEQ_HPP
+
+#include <boost/preprocessor/seq/size.hpp>
+#include <boost/preprocessor/seq/push_back.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_AUGMENT_BINARY_SEQ_INDEX_FOLD_OP(s, seq, idx) \
+ BOOST_PP_SEQ_PUSH_BACK(seq, (idx, BOOST_PP_SEQ_SIZE(seq)))
+/**/
+
+#include <boost/preprocessor/control/iif.hpp>
+#include <boost/preprocessor/seq/elem.hpp>
+#include <boost/preprocessor/tuple/elem.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_CONVERT_BINARY_SEQ_FOLD_OP(s, seq, elem) \
+ ( \
+ BOOST_PP_SEQ_PUSH_BACK( \
+ BOOST_PP_SEQ_ELEM(0, seq) \
+ , BOOST_PP_IIF( \
+ BOOST_PP_TUPLE_ELEM(2, 0, elem) \
+ , BOOST_PP_SEQ_ELEM(2, seq) \
+ , BOOST_PP_SEQ_ELEM(1, seq) \
+ )(BOOST_PP_TUPLE_ELEM(2, 1, elem), BOOST_PP_SEQ_ELEM(3, seq)) \
+ ) \
+ )(BOOST_PP_SEQ_ELEM(1, seq))(BOOST_PP_SEQ_ELEM(2, seq)) \
+ (BOOST_PP_SEQ_ELEM(3, seq))
+/**/
+
+#include <boost/parameter/aux_/preprocessor/seq_enum.hpp>
+#include <boost/preprocessor/facilities/empty.hpp>
+#include <boost/preprocessor/seq/seq.hpp>
+#include <boost/preprocessor/seq/fold_left.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_CONVERT_BINARY_SEQ(seq, macro0, macro1, data) \
+ BOOST_PARAMETER_SEQ_ENUM( \
+ BOOST_PP_SEQ_ELEM( \
+ 0 \
+ , BOOST_PP_SEQ_FOLD_LEFT( \
+ BOOST_PARAMETER_AUX_PP_CONVERT_BINARY_SEQ_FOLD_OP \
+ , (BOOST_PP_SEQ_NIL)(macro0)(macro1)(data) \
+ , BOOST_PP_SEQ_FOLD_LEFT( \
+ BOOST_PARAMETER_AUX_PP_AUGMENT_BINARY_SEQ_INDEX_FOLD_OP \
+ , BOOST_PP_EMPTY() \
+ , seq \
+ ) \
+ ) \
+ ) \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/flatten.hpp b/boost/parameter/aux_/preprocessor/flatten.hpp
index 5d7615e3f3..876a928bfd 100644
--- a/boost/parameter/aux_/preprocessor/flatten.hpp
+++ b/boost/parameter/aux_/preprocessor/flatten.hpp
@@ -1,115 +1,12 @@
-// Copyright Daniel Wallin 2005. Use, modification and distribution is
-// subject to the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright Daniel Wallin 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARAMETER_FLATTEN_051217_HPP
-# define BOOST_PARAMETER_FLATTEN_051217_HPP
+#define BOOST_PARAMETER_FLATTEN_051217_HPP
-# include <boost/preprocessor/tuple/elem.hpp>
-# include <boost/preprocessor/tuple/rem.hpp>
-# include <boost/preprocessor/cat.hpp>
-# include <boost/preprocessor/seq/for_each.hpp>
-# include <boost/preprocessor/seq/for_each_i.hpp>
-# include <boost/preprocessor/identity.hpp>
-# include <boost/preprocessor/selection/max.hpp>
-# include <boost/preprocessor/arithmetic/sub.hpp>
-# include <boost/preprocessor/repetition/enum_trailing.hpp>
-# include <boost/parameter/aux_/preprocessor/for_each.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/flatten.hpp>
-# define BOOST_PARAMETER_FLATTEN_SPLIT_required required,
-# define BOOST_PARAMETER_FLATTEN_SPLIT_optional optional,
-# define BOOST_PARAMETER_FLATTEN_SPLIT_deduced deduced,
-
-# define BOOST_PARAMETER_FLATTEN_SPLIT(sub) \
- BOOST_PP_CAT(BOOST_PARAMETER_FLATTEN_SPLIT_, sub)
-
-# define BOOST_PARAMETER_FLATTEN_QUALIFIER(sub) \
- BOOST_PP_SPLIT(0, BOOST_PARAMETER_FLATTEN_SPLIT(sub))
-
-# define BOOST_PARAMETER_FLATTEN_ARGS(sub) \
- BOOST_PP_SPLIT(1, BOOST_PARAMETER_FLATTEN_SPLIT(sub))
-
-# define BOOST_PARAMETER_FLATTEN_ARITY_optional(arities) \
- BOOST_PP_TUPLE_ELEM(3,0,arities)
-
-# define BOOST_PARAMETER_FLATTEN_ARITY_required(arities) \
- BOOST_PP_TUPLE_ELEM(3,1,arities)
-
-# define BOOST_PARAMETER_FLATTEN_SPEC0_DUMMY_ELEM(z, n, data) ~
-# define BOOST_PARAMETER_FLATTEN_SPEC0(r, n, elem, data) \
- (( \
- BOOST_PP_TUPLE_ELEM(3,2,data) \
- , BOOST_PP_TUPLE_REM(BOOST_PP_TUPLE_ELEM(3,0,data)) elem \
- BOOST_PP_ENUM_TRAILING( \
- BOOST_PP_SUB( \
- BOOST_PP_TUPLE_ELEM(3,1,data) \
- , BOOST_PP_TUPLE_ELEM(3,0,data) \
- ) \
- , BOOST_PARAMETER_FLATTEN_SPEC0_DUMMY_ELEM \
- , ~ \
- ) \
- ))
-
-# define BOOST_PARAMETER_FLATTEN_SPEC_AUX(r, arity, max_arity, spec, transform) \
- BOOST_PARAMETER_FOR_EACH_R( \
- r \
- , arity \
- , BOOST_PARAMETER_FLATTEN_ARGS(spec) \
- , (arity, max_arity, transform(BOOST_PARAMETER_FLATTEN_QUALIFIER(spec))) \
- , BOOST_PARAMETER_FLATTEN_SPEC0 \
- )
-
-# define BOOST_PARAMETER_FLATTEN_IDENTITY(x) x
-
-# define BOOST_PARAMETER_FLATTEN_SPEC_optional(r, arities, spec) \
- BOOST_PARAMETER_FLATTEN_SPEC_AUX( \
- r \
- , BOOST_PP_CAT( \
- BOOST_PARAMETER_FLATTEN_ARITY_, BOOST_PARAMETER_FLATTEN_QUALIFIER(spec) \
- )(arities) \
- , BOOST_PP_TUPLE_ELEM(3,2,arities) \
- , spec \
- , BOOST_PARAMETER_FLATTEN_IDENTITY \
- )
-
-# define BOOST_PARAMETER_FLATTEN_SPEC_required(r, arities, spec) \
- BOOST_PARAMETER_FLATTEN_SPEC_optional(r, arities, spec)
-
-# define BOOST_PARAMETER_FLATTEN_SPEC_AS_DEDUCED(x) BOOST_PP_CAT(deduced_,x)
-
-# define BOOST_PARAMETER_FLATTEN_SPEC_deduced_M(r, arities, n, spec) \
- BOOST_PARAMETER_FLATTEN_SPEC_AUX( \
- r \
- , BOOST_PP_CAT( \
- BOOST_PARAMETER_FLATTEN_ARITY_, BOOST_PARAMETER_FLATTEN_QUALIFIER(spec) \
- )(arities) \
- , BOOST_PP_TUPLE_ELEM(3,2,arities) \
- , spec \
- , BOOST_PARAMETER_FLATTEN_SPEC_AS_DEDUCED \
- )
-
-# define BOOST_PARAMETER_FLATTEN_SPEC_deduced(r, arities, spec) \
- BOOST_PP_SEQ_FOR_EACH_I_R( \
- r \
- , BOOST_PARAMETER_FLATTEN_SPEC_deduced_M \
- , arities \
- , BOOST_PARAMETER_FLATTEN_ARGS(spec) \
- )
-
-# define BOOST_PARAMETER_FLATTEN_SPEC(r, arities, spec) \
- BOOST_PP_CAT( \
- BOOST_PARAMETER_FLATTEN_SPEC_, BOOST_PARAMETER_FLATTEN_QUALIFIER(spec) \
- )(r, arities, spec)
-
-# define BOOST_PARAMETER_FLATTEN(optional_arity, required_arity, wanted_arity, specs) \
- BOOST_PP_SEQ_FOR_EACH( \
- BOOST_PARAMETER_FLATTEN_SPEC \
- , ( \
- optional_arity, required_arity \
- , wanted_arity \
- ) \
- , specs \
- )
-
-#endif // BOOST_PARAMETER_FLATTEN_051217_HPP
+#endif // include guard
diff --git a/boost/parameter/aux_/preprocessor/for_each.hpp b/boost/parameter/aux_/preprocessor/for_each.hpp
index 0eb1f702db..221f45a785 100644
--- a/boost/parameter/aux_/preprocessor/for_each.hpp
+++ b/boost/parameter/aux_/preprocessor/for_each.hpp
@@ -1,103 +1,12 @@
-// Copyright Daniel Wallin 2005. Use, modification and distribution is
-// subject to the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright Daniel Wallin 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARAMETER_FOR_EACH_051217_HPP
-# define BOOST_PARAMETER_FOR_EACH_051217_HPP
+#define BOOST_PARAMETER_FOR_EACH_051217_HPP
-# include <boost/preprocessor/cat.hpp>
-# include <boost/preprocessor/detail/split.hpp>
-# include <boost/preprocessor/logical/not.hpp>
-# include <boost/preprocessor/facilities/is_empty.hpp>
-# include <boost/preprocessor/tuple/eat.hpp>
-# include <boost/preprocessor/arithmetic/inc.hpp>
-# include <boost/preprocessor/repeat.hpp>
-# include <boost/preprocessor/punctuation/comma_if.hpp>
-# include <boost/preprocessor/for.hpp>
-# include <boost/preprocessor/repetition/deduce_r.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/for_each.hpp>
-# define BOOST_PARAMETER_FOR_EACH_head_aux2(x,y) (x,y), ~
-# define BOOST_PARAMETER_FOR_EACH_head_aux3(x,y,z) (x,y,z), ~
-# define BOOST_PARAMETER_FOR_EACH_head_aux4(x,y,z,u) (x,y,z,u), ~
-# define BOOST_PARAMETER_FOR_EACH_head(n,x) \
- BOOST_PP_SPLIT(0, BOOST_PP_CAT(BOOST_PARAMETER_FOR_EACH_head_aux,n) x)
-
-# define BOOST_PARAMETER_FOR_EACH_pred_aux_BOOST_PARAMETER_FOR_EACH_END_SENTINEL
-# define BOOST_PARAMETER_FOR_EACH_pred_aux_check(x) \
- BOOST_PP_NOT(BOOST_PP_IS_EMPTY( \
- BOOST_PP_CAT(BOOST_PARAMETER_FOR_EACH_pred_aux_, x) \
- )), ~
-
-# define BOOST_PARAMETER_FOR_EACH_pred_aux2(x,y) \
- BOOST_PARAMETER_FOR_EACH_pred_aux_check(x)
-# define BOOST_PARAMETER_FOR_EACH_pred_aux3(x,y,z) \
- BOOST_PARAMETER_FOR_EACH_pred_aux_check(x)
-# define BOOST_PARAMETER_FOR_EACH_pred_aux4(x,y,z,u) \
- BOOST_PARAMETER_FOR_EACH_pred_aux_check(x)
-
-# define BOOST_PARAMETER_FOR_EACH_pred_aux0(n,x) \
- BOOST_PP_CAT(BOOST_PARAMETER_FOR_EACH_pred_aux,n) x
-
-# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
-# define BOOST_PARAMETER_FOR_EACH_pred_SPLIT_FIRST(x) \
- BOOST_PP_SPLIT(0, x)
-
-# define BOOST_PARAMETER_FOR_EACH_pred(r, state) \
- BOOST_PARAMETER_FOR_EACH_pred_SPLIT_FIRST( \
- BOOST_PARAMETER_FOR_EACH_pred_aux0( \
- BOOST_PP_TUPLE_ELEM(5,3,state) \
- , BOOST_PP_TUPLE_ELEM(5,0,state) \
- ) \
- )
-# else
-# define BOOST_PARAMETER_FOR_EACH_pred(r, state) \
- BOOST_PP_SPLIT( \
- 0 \
- , BOOST_PARAMETER_FOR_EACH_pred_aux0( \
- BOOST_PP_TUPLE_ELEM(5,3,state) \
- , BOOST_PP_TUPLE_ELEM(5,0,state) \
- ) \
- )
-# endif
-
-# define BOOST_PARAMETER_FOR_EACH_op(r, state) \
- ( \
- BOOST_PP_TUPLE_EAT(BOOST_PP_TUPLE_ELEM(5,3,state)) \
- BOOST_PP_TUPLE_ELEM(5,0,state) \
- , BOOST_PP_TUPLE_ELEM(5,1,state) \
- , BOOST_PP_TUPLE_ELEM(5,2,state) \
- , BOOST_PP_TUPLE_ELEM(5,3,state) \
- , BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(5,4,state)) \
- )
-
-# define BOOST_PARAMETER_FOR_EACH_macro(r, state) \
- BOOST_PP_TUPLE_ELEM(5,2,state)( \
- r \
- , BOOST_PP_TUPLE_ELEM(5,4,state) \
- , BOOST_PARAMETER_FOR_EACH_head( \
- BOOST_PP_TUPLE_ELEM(5,3,state) \
- , BOOST_PP_TUPLE_ELEM(5,0,state) \
- ) \
- , BOOST_PP_TUPLE_ELEM(5,1,state) \
- )
-
-# define BOOST_PARAMETER_FOR_EACH_build_end_sentinel(z,n,text) \
- BOOST_PP_COMMA_IF(n) BOOST_PARAMETER_FOR_EACH_END_SENTINEL
-# define BOOST_PARAMETER_FOR_EACH_build_end_sentinel_tuple(arity) \
- ( \
- BOOST_PP_REPEAT(arity, BOOST_PARAMETER_FOR_EACH_build_end_sentinel, _) \
- )
-
-# define BOOST_PARAMETER_FOR_EACH_R(r, arity, list, data, macro) \
- BOOST_PP_CAT(BOOST_PP_FOR_, r)( \
- (list BOOST_PARAMETER_FOR_EACH_build_end_sentinel_tuple(arity), data, macro, arity, 0) \
- , BOOST_PARAMETER_FOR_EACH_pred \
- , BOOST_PARAMETER_FOR_EACH_op \
- , BOOST_PARAMETER_FOR_EACH_macro \
- )
-
-# define BOOST_PARAMETER_FOR_EACH(arity, list, data, macro) \
- BOOST_PARAMETER_FOR_EACH_R(BOOST_PP_DEDUCE_R(), arity, list, data, macro)
-
-#endif // BOOST_PARAMETER_FOR_EACH_051217_HPP
+#endif // include guard
diff --git a/boost/parameter/aux_/preprocessor/for_each_pred.hpp b/boost/parameter/aux_/preprocessor/for_each_pred.hpp
new file mode 100644
index 0000000000..7d4c6368e6
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/for_each_pred.hpp
@@ -0,0 +1,1029 @@
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PREPROCESSOR_FOR_EACH_PRED_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_FOR_EACH_PRED_HPP
+
+#include <boost/preprocessor/comparison/not_equal.hpp>
+#include <boost/preprocessor/seq/size.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_1(r, seq) \
+ BOOST_PP_NOT_EQUAL(2, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_2(r, seq) \
+ BOOST_PP_NOT_EQUAL(3, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_3(r, seq) \
+ BOOST_PP_NOT_EQUAL(4, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_4(r, seq) \
+ BOOST_PP_NOT_EQUAL(5, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_5(r, seq) \
+ BOOST_PP_NOT_EQUAL(6, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_6(r, seq) \
+ BOOST_PP_NOT_EQUAL(7, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_7(r, seq) \
+ BOOST_PP_NOT_EQUAL(8, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_8(r, seq) \
+ BOOST_PP_NOT_EQUAL(9, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_9(r, seq) \
+ BOOST_PP_NOT_EQUAL(10, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_10(r, seq) \
+ BOOST_PP_NOT_EQUAL(11, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_11(r, seq) \
+ BOOST_PP_NOT_EQUAL(12, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_12(r, seq) \
+ BOOST_PP_NOT_EQUAL(13, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_13(r, seq) \
+ BOOST_PP_NOT_EQUAL(14, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_14(r, seq) \
+ BOOST_PP_NOT_EQUAL(15, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_15(r, seq) \
+ BOOST_PP_NOT_EQUAL(16, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_16(r, seq) \
+ BOOST_PP_NOT_EQUAL(17, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_17(r, seq) \
+ BOOST_PP_NOT_EQUAL(18, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_18(r, seq) \
+ BOOST_PP_NOT_EQUAL(19, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_19(r, seq) \
+ BOOST_PP_NOT_EQUAL(20, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_20(r, seq) \
+ BOOST_PP_NOT_EQUAL(21, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_21(r, seq) \
+ BOOST_PP_NOT_EQUAL(22, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_22(r, seq) \
+ BOOST_PP_NOT_EQUAL(23, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_23(r, seq) \
+ BOOST_PP_NOT_EQUAL(24, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_24(r, seq) \
+ BOOST_PP_NOT_EQUAL(25, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_25(r, seq) \
+ BOOST_PP_NOT_EQUAL(26, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_26(r, seq) \
+ BOOST_PP_NOT_EQUAL(27, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_27(r, seq) \
+ BOOST_PP_NOT_EQUAL(28, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_28(r, seq) \
+ BOOST_PP_NOT_EQUAL(29, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_29(r, seq) \
+ BOOST_PP_NOT_EQUAL(30, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_30(r, seq) \
+ BOOST_PP_NOT_EQUAL(31, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_31(r, seq) \
+ BOOST_PP_NOT_EQUAL(32, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_32(r, seq) \
+ BOOST_PP_NOT_EQUAL(33, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_33(r, seq) \
+ BOOST_PP_NOT_EQUAL(34, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_34(r, seq) \
+ BOOST_PP_NOT_EQUAL(35, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_35(r, seq) \
+ BOOST_PP_NOT_EQUAL(36, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_36(r, seq) \
+ BOOST_PP_NOT_EQUAL(37, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_37(r, seq) \
+ BOOST_PP_NOT_EQUAL(38, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_38(r, seq) \
+ BOOST_PP_NOT_EQUAL(39, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_39(r, seq) \
+ BOOST_PP_NOT_EQUAL(40, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_40(r, seq) \
+ BOOST_PP_NOT_EQUAL(41, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_41(r, seq) \
+ BOOST_PP_NOT_EQUAL(42, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_42(r, seq) \
+ BOOST_PP_NOT_EQUAL(43, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_43(r, seq) \
+ BOOST_PP_NOT_EQUAL(44, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_44(r, seq) \
+ BOOST_PP_NOT_EQUAL(45, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_45(r, seq) \
+ BOOST_PP_NOT_EQUAL(46, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_46(r, seq) \
+ BOOST_PP_NOT_EQUAL(47, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_47(r, seq) \
+ BOOST_PP_NOT_EQUAL(48, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_48(r, seq) \
+ BOOST_PP_NOT_EQUAL(49, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_49(r, seq) \
+ BOOST_PP_NOT_EQUAL(50, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_50(r, seq) \
+ BOOST_PP_NOT_EQUAL(51, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_51(r, seq) \
+ BOOST_PP_NOT_EQUAL(52, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_52(r, seq) \
+ BOOST_PP_NOT_EQUAL(53, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_53(r, seq) \
+ BOOST_PP_NOT_EQUAL(54, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_54(r, seq) \
+ BOOST_PP_NOT_EQUAL(55, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_55(r, seq) \
+ BOOST_PP_NOT_EQUAL(56, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_56(r, seq) \
+ BOOST_PP_NOT_EQUAL(57, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_57(r, seq) \
+ BOOST_PP_NOT_EQUAL(58, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_58(r, seq) \
+ BOOST_PP_NOT_EQUAL(59, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_59(r, seq) \
+ BOOST_PP_NOT_EQUAL(60, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_60(r, seq) \
+ BOOST_PP_NOT_EQUAL(61, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_61(r, seq) \
+ BOOST_PP_NOT_EQUAL(62, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_62(r, seq) \
+ BOOST_PP_NOT_EQUAL(63, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_63(r, seq) \
+ BOOST_PP_NOT_EQUAL(64, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_64(r, seq) \
+ BOOST_PP_NOT_EQUAL(65, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_65(r, seq) \
+ BOOST_PP_NOT_EQUAL(66, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_66(r, seq) \
+ BOOST_PP_NOT_EQUAL(67, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_67(r, seq) \
+ BOOST_PP_NOT_EQUAL(68, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_68(r, seq) \
+ BOOST_PP_NOT_EQUAL(69, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_69(r, seq) \
+ BOOST_PP_NOT_EQUAL(70, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_70(r, seq) \
+ BOOST_PP_NOT_EQUAL(71, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_71(r, seq) \
+ BOOST_PP_NOT_EQUAL(72, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_72(r, seq) \
+ BOOST_PP_NOT_EQUAL(73, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_73(r, seq) \
+ BOOST_PP_NOT_EQUAL(74, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_74(r, seq) \
+ BOOST_PP_NOT_EQUAL(75, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_75(r, seq) \
+ BOOST_PP_NOT_EQUAL(76, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_76(r, seq) \
+ BOOST_PP_NOT_EQUAL(77, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_77(r, seq) \
+ BOOST_PP_NOT_EQUAL(78, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_78(r, seq) \
+ BOOST_PP_NOT_EQUAL(79, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_79(r, seq) \
+ BOOST_PP_NOT_EQUAL(80, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_80(r, seq) \
+ BOOST_PP_NOT_EQUAL(81, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_81(r, seq) \
+ BOOST_PP_NOT_EQUAL(82, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_82(r, seq) \
+ BOOST_PP_NOT_EQUAL(83, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_83(r, seq) \
+ BOOST_PP_NOT_EQUAL(84, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_84(r, seq) \
+ BOOST_PP_NOT_EQUAL(85, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_85(r, seq) \
+ BOOST_PP_NOT_EQUAL(86, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_86(r, seq) \
+ BOOST_PP_NOT_EQUAL(87, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_87(r, seq) \
+ BOOST_PP_NOT_EQUAL(88, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_88(r, seq) \
+ BOOST_PP_NOT_EQUAL(89, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_89(r, seq) \
+ BOOST_PP_NOT_EQUAL(90, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_90(r, seq) \
+ BOOST_PP_NOT_EQUAL(91, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_91(r, seq) \
+ BOOST_PP_NOT_EQUAL(92, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_92(r, seq) \
+ BOOST_PP_NOT_EQUAL(93, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_93(r, seq) \
+ BOOST_PP_NOT_EQUAL(94, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_94(r, seq) \
+ BOOST_PP_NOT_EQUAL(95, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_95(r, seq) \
+ BOOST_PP_NOT_EQUAL(96, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_96(r, seq) \
+ BOOST_PP_NOT_EQUAL(97, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_97(r, seq) \
+ BOOST_PP_NOT_EQUAL(98, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_98(r, seq) \
+ BOOST_PP_NOT_EQUAL(99, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_99(r, seq) \
+ BOOST_PP_NOT_EQUAL(100, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_100(r, seq) \
+ BOOST_PP_NOT_EQUAL(101, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_101(r, seq) \
+ BOOST_PP_NOT_EQUAL(102, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_102(r, seq) \
+ BOOST_PP_NOT_EQUAL(103, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_103(r, seq) \
+ BOOST_PP_NOT_EQUAL(104, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_104(r, seq) \
+ BOOST_PP_NOT_EQUAL(105, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_105(r, seq) \
+ BOOST_PP_NOT_EQUAL(106, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_106(r, seq) \
+ BOOST_PP_NOT_EQUAL(107, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_107(r, seq) \
+ BOOST_PP_NOT_EQUAL(108, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_108(r, seq) \
+ BOOST_PP_NOT_EQUAL(109, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_109(r, seq) \
+ BOOST_PP_NOT_EQUAL(110, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_110(r, seq) \
+ BOOST_PP_NOT_EQUAL(111, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_111(r, seq) \
+ BOOST_PP_NOT_EQUAL(112, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_112(r, seq) \
+ BOOST_PP_NOT_EQUAL(113, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_113(r, seq) \
+ BOOST_PP_NOT_EQUAL(114, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_114(r, seq) \
+ BOOST_PP_NOT_EQUAL(115, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_115(r, seq) \
+ BOOST_PP_NOT_EQUAL(116, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_116(r, seq) \
+ BOOST_PP_NOT_EQUAL(117, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_117(r, seq) \
+ BOOST_PP_NOT_EQUAL(118, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_118(r, seq) \
+ BOOST_PP_NOT_EQUAL(119, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_119(r, seq) \
+ BOOST_PP_NOT_EQUAL(120, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_120(r, seq) \
+ BOOST_PP_NOT_EQUAL(121, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_121(r, seq) \
+ BOOST_PP_NOT_EQUAL(122, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_122(r, seq) \
+ BOOST_PP_NOT_EQUAL(123, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_123(r, seq) \
+ BOOST_PP_NOT_EQUAL(124, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_124(r, seq) \
+ BOOST_PP_NOT_EQUAL(125, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_125(r, seq) \
+ BOOST_PP_NOT_EQUAL(126, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_126(r, seq) \
+ BOOST_PP_NOT_EQUAL(127, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_127(r, seq) \
+ BOOST_PP_NOT_EQUAL(128, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_128(r, seq) \
+ BOOST_PP_NOT_EQUAL(129, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_129(r, seq) \
+ BOOST_PP_NOT_EQUAL(130, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_130(r, seq) \
+ BOOST_PP_NOT_EQUAL(131, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_131(r, seq) \
+ BOOST_PP_NOT_EQUAL(132, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_132(r, seq) \
+ BOOST_PP_NOT_EQUAL(133, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_133(r, seq) \
+ BOOST_PP_NOT_EQUAL(134, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_134(r, seq) \
+ BOOST_PP_NOT_EQUAL(135, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_135(r, seq) \
+ BOOST_PP_NOT_EQUAL(136, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_136(r, seq) \
+ BOOST_PP_NOT_EQUAL(137, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_137(r, seq) \
+ BOOST_PP_NOT_EQUAL(138, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_138(r, seq) \
+ BOOST_PP_NOT_EQUAL(139, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_139(r, seq) \
+ BOOST_PP_NOT_EQUAL(140, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_140(r, seq) \
+ BOOST_PP_NOT_EQUAL(141, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_141(r, seq) \
+ BOOST_PP_NOT_EQUAL(142, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_142(r, seq) \
+ BOOST_PP_NOT_EQUAL(143, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_143(r, seq) \
+ BOOST_PP_NOT_EQUAL(144, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_144(r, seq) \
+ BOOST_PP_NOT_EQUAL(145, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_145(r, seq) \
+ BOOST_PP_NOT_EQUAL(146, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_146(r, seq) \
+ BOOST_PP_NOT_EQUAL(147, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_147(r, seq) \
+ BOOST_PP_NOT_EQUAL(148, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_148(r, seq) \
+ BOOST_PP_NOT_EQUAL(149, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_149(r, seq) \
+ BOOST_PP_NOT_EQUAL(150, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_150(r, seq) \
+ BOOST_PP_NOT_EQUAL(151, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_151(r, seq) \
+ BOOST_PP_NOT_EQUAL(152, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_152(r, seq) \
+ BOOST_PP_NOT_EQUAL(153, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_153(r, seq) \
+ BOOST_PP_NOT_EQUAL(154, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_154(r, seq) \
+ BOOST_PP_NOT_EQUAL(155, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_155(r, seq) \
+ BOOST_PP_NOT_EQUAL(156, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_156(r, seq) \
+ BOOST_PP_NOT_EQUAL(157, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_157(r, seq) \
+ BOOST_PP_NOT_EQUAL(158, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_158(r, seq) \
+ BOOST_PP_NOT_EQUAL(159, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_159(r, seq) \
+ BOOST_PP_NOT_EQUAL(160, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_160(r, seq) \
+ BOOST_PP_NOT_EQUAL(161, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_161(r, seq) \
+ BOOST_PP_NOT_EQUAL(162, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_162(r, seq) \
+ BOOST_PP_NOT_EQUAL(163, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_163(r, seq) \
+ BOOST_PP_NOT_EQUAL(164, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_164(r, seq) \
+ BOOST_PP_NOT_EQUAL(165, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_165(r, seq) \
+ BOOST_PP_NOT_EQUAL(166, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_166(r, seq) \
+ BOOST_PP_NOT_EQUAL(167, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_167(r, seq) \
+ BOOST_PP_NOT_EQUAL(168, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_168(r, seq) \
+ BOOST_PP_NOT_EQUAL(169, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_169(r, seq) \
+ BOOST_PP_NOT_EQUAL(170, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_170(r, seq) \
+ BOOST_PP_NOT_EQUAL(171, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_171(r, seq) \
+ BOOST_PP_NOT_EQUAL(172, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_172(r, seq) \
+ BOOST_PP_NOT_EQUAL(173, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_173(r, seq) \
+ BOOST_PP_NOT_EQUAL(174, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_174(r, seq) \
+ BOOST_PP_NOT_EQUAL(175, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_175(r, seq) \
+ BOOST_PP_NOT_EQUAL(176, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_176(r, seq) \
+ BOOST_PP_NOT_EQUAL(177, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_177(r, seq) \
+ BOOST_PP_NOT_EQUAL(178, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_178(r, seq) \
+ BOOST_PP_NOT_EQUAL(179, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_179(r, seq) \
+ BOOST_PP_NOT_EQUAL(180, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_180(r, seq) \
+ BOOST_PP_NOT_EQUAL(181, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_181(r, seq) \
+ BOOST_PP_NOT_EQUAL(182, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_182(r, seq) \
+ BOOST_PP_NOT_EQUAL(183, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_183(r, seq) \
+ BOOST_PP_NOT_EQUAL(184, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_184(r, seq) \
+ BOOST_PP_NOT_EQUAL(185, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_185(r, seq) \
+ BOOST_PP_NOT_EQUAL(186, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_186(r, seq) \
+ BOOST_PP_NOT_EQUAL(187, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_187(r, seq) \
+ BOOST_PP_NOT_EQUAL(188, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_188(r, seq) \
+ BOOST_PP_NOT_EQUAL(189, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_189(r, seq) \
+ BOOST_PP_NOT_EQUAL(190, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_190(r, seq) \
+ BOOST_PP_NOT_EQUAL(191, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_191(r, seq) \
+ BOOST_PP_NOT_EQUAL(192, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_192(r, seq) \
+ BOOST_PP_NOT_EQUAL(193, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_193(r, seq) \
+ BOOST_PP_NOT_EQUAL(194, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_194(r, seq) \
+ BOOST_PP_NOT_EQUAL(195, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_195(r, seq) \
+ BOOST_PP_NOT_EQUAL(196, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_196(r, seq) \
+ BOOST_PP_NOT_EQUAL(197, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_197(r, seq) \
+ BOOST_PP_NOT_EQUAL(198, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_198(r, seq) \
+ BOOST_PP_NOT_EQUAL(199, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_199(r, seq) \
+ BOOST_PP_NOT_EQUAL(200, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_200(r, seq) \
+ BOOST_PP_NOT_EQUAL(201, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_201(r, seq) \
+ BOOST_PP_NOT_EQUAL(202, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_202(r, seq) \
+ BOOST_PP_NOT_EQUAL(203, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_203(r, seq) \
+ BOOST_PP_NOT_EQUAL(204, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_204(r, seq) \
+ BOOST_PP_NOT_EQUAL(205, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_205(r, seq) \
+ BOOST_PP_NOT_EQUAL(206, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_206(r, seq) \
+ BOOST_PP_NOT_EQUAL(207, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_207(r, seq) \
+ BOOST_PP_NOT_EQUAL(208, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_208(r, seq) \
+ BOOST_PP_NOT_EQUAL(209, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_209(r, seq) \
+ BOOST_PP_NOT_EQUAL(210, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_210(r, seq) \
+ BOOST_PP_NOT_EQUAL(211, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_211(r, seq) \
+ BOOST_PP_NOT_EQUAL(212, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_212(r, seq) \
+ BOOST_PP_NOT_EQUAL(213, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_213(r, seq) \
+ BOOST_PP_NOT_EQUAL(214, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_214(r, seq) \
+ BOOST_PP_NOT_EQUAL(215, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_215(r, seq) \
+ BOOST_PP_NOT_EQUAL(216, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_216(r, seq) \
+ BOOST_PP_NOT_EQUAL(217, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_217(r, seq) \
+ BOOST_PP_NOT_EQUAL(218, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_218(r, seq) \
+ BOOST_PP_NOT_EQUAL(219, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_219(r, seq) \
+ BOOST_PP_NOT_EQUAL(220, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_220(r, seq) \
+ BOOST_PP_NOT_EQUAL(221, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_221(r, seq) \
+ BOOST_PP_NOT_EQUAL(222, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_222(r, seq) \
+ BOOST_PP_NOT_EQUAL(223, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_223(r, seq) \
+ BOOST_PP_NOT_EQUAL(224, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_224(r, seq) \
+ BOOST_PP_NOT_EQUAL(225, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_225(r, seq) \
+ BOOST_PP_NOT_EQUAL(226, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_226(r, seq) \
+ BOOST_PP_NOT_EQUAL(227, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_227(r, seq) \
+ BOOST_PP_NOT_EQUAL(228, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_228(r, seq) \
+ BOOST_PP_NOT_EQUAL(229, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_229(r, seq) \
+ BOOST_PP_NOT_EQUAL(230, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_230(r, seq) \
+ BOOST_PP_NOT_EQUAL(231, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_231(r, seq) \
+ BOOST_PP_NOT_EQUAL(232, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_232(r, seq) \
+ BOOST_PP_NOT_EQUAL(233, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_233(r, seq) \
+ BOOST_PP_NOT_EQUAL(234, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_234(r, seq) \
+ BOOST_PP_NOT_EQUAL(235, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_235(r, seq) \
+ BOOST_PP_NOT_EQUAL(236, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_236(r, seq) \
+ BOOST_PP_NOT_EQUAL(237, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_237(r, seq) \
+ BOOST_PP_NOT_EQUAL(238, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_238(r, seq) \
+ BOOST_PP_NOT_EQUAL(239, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_239(r, seq) \
+ BOOST_PP_NOT_EQUAL(240, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_240(r, seq) \
+ BOOST_PP_NOT_EQUAL(241, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_241(r, seq) \
+ BOOST_PP_NOT_EQUAL(242, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_242(r, seq) \
+ BOOST_PP_NOT_EQUAL(243, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_243(r, seq) \
+ BOOST_PP_NOT_EQUAL(244, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_244(r, seq) \
+ BOOST_PP_NOT_EQUAL(245, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_245(r, seq) \
+ BOOST_PP_NOT_EQUAL(246, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_246(r, seq) \
+ BOOST_PP_NOT_EQUAL(247, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_247(r, seq) \
+ BOOST_PP_NOT_EQUAL(248, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_248(r, seq) \
+ BOOST_PP_NOT_EQUAL(249, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_249(r, seq) \
+ BOOST_PP_NOT_EQUAL(250, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_250(r, seq) \
+ BOOST_PP_NOT_EQUAL(251, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_251(r, seq) \
+ BOOST_PP_NOT_EQUAL(252, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_252(r, seq) \
+ BOOST_PP_NOT_EQUAL(253, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_253(r, seq) \
+ BOOST_PP_NOT_EQUAL(254, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_PRED_254(r, seq) \
+ BOOST_PP_NOT_EQUAL(255, BOOST_PP_SEQ_SIZE(seq))
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/argument_specs.hpp b/boost/parameter/aux_/preprocessor/impl/argument_specs.hpp
new file mode 100644
index 0000000000..1efce38864
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/argument_specs.hpp
@@ -0,0 +1,24 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_ARGUMENT_SPECS_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_ARGUMENT_SPECS_HPP
+
+#include <boost/preprocessor/tuple/elem.hpp>
+
+// Accessor macros for the argument specs tuple.
+#define BOOST_PARAMETER_FN_ARG_QUALIFIER(x) BOOST_PP_TUPLE_ELEM(4, 0, x)
+#define BOOST_PARAMETER_FN_ARG_KEYWORD(x) BOOST_PP_TUPLE_ELEM(4, 1, x)
+#define BOOST_PARAMETER_FN_ARG_PRED(x) BOOST_PP_TUPLE_ELEM(4, 2, x)
+#define BOOST_PARAMETER_FN_ARG_DEFAULT(x) BOOST_PP_TUPLE_ELEM(4, 3, x)
+
+#include <boost/parameter/aux_/preprocessor/qualifier.hpp>
+
+#define BOOST_PARAMETER_FN_ARG_NAME(x) \
+ BOOST_PARAMETER_UNQUALIFIED(BOOST_PARAMETER_FN_ARG_KEYWORD(x))
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/arity_range.hpp b/boost/parameter/aux_/preprocessor/impl/arity_range.hpp
new file mode 100644
index 0000000000..848648e4cc
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/arity_range.hpp
@@ -0,0 +1,42 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_ARITY_RANGE_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_ARITY_RANGE_HPP
+
+// Helper macros for BOOST_PARAMETER_ARITY_RANGE.
+#define BOOST_PARAMETER_ARITY_RANGE_M_optional(state) state
+#define BOOST_PARAMETER_ARITY_RANGE_M_deduced_optional(state) state
+
+#include <boost/preprocessor/arithmetic/inc.hpp>
+
+#define BOOST_PARAMETER_ARITY_RANGE_M_required(state) BOOST_PP_INC(state)
+#define BOOST_PARAMETER_ARITY_RANGE_M_deduced_required(state) \
+ BOOST_PP_INC(state)
+/**/
+
+#include <boost/parameter/aux_/preprocessor/impl/argument_specs.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+#define BOOST_PARAMETER_ARITY_RANGE_M(s, state, x) \
+ BOOST_PP_CAT( \
+ BOOST_PARAMETER_ARITY_RANGE_M_ \
+ , BOOST_PARAMETER_FN_ARG_QUALIFIER(x) \
+ )(state)
+/**/
+
+#include <boost/preprocessor/seq/fold_left.hpp>
+#include <boost/preprocessor/seq/size.hpp>
+
+// Calculates [begin, end) arity range.
+#define BOOST_PARAMETER_ARITY_RANGE(args) \
+ ( \
+ BOOST_PP_SEQ_FOLD_LEFT(BOOST_PARAMETER_ARITY_RANGE_M, 0, args) \
+ , BOOST_PP_INC(BOOST_PP_SEQ_SIZE(args)) \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/flatten.hpp b/boost/parameter/aux_/preprocessor/impl/flatten.hpp
new file mode 100644
index 0000000000..0d23a0c3b3
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/flatten.hpp
@@ -0,0 +1,143 @@
+// Copyright Daniel Wallin 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FLATTEN_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FLATTEN_HPP
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPLIT_required required,
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPLIT_optional optional,
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPLIT_deduced deduced,
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_IDENTITY(x) x
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC0_DUMMY_ELEM(z, n, data) ~
+
+#include <boost/preprocessor/cat.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPLIT(sub) \
+ BOOST_PP_CAT(BOOST_PARAMETER_AUX_PP_FLATTEN_SPLIT_, sub)
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_AS_DEDUCED(x) \
+ BOOST_PP_CAT(deduced_, x)
+/**/
+
+#include <boost/preprocessor/detail/split.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_QUALIFIER(sub) \
+ BOOST_PP_SPLIT(0, BOOST_PARAMETER_AUX_PP_FLATTEN_SPLIT(sub))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_ARGS(sub) \
+ BOOST_PP_SPLIT(1, BOOST_PARAMETER_AUX_PP_FLATTEN_SPLIT(sub))
+/**/
+
+#include <boost/preprocessor/tuple/elem.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_ARITY_optional(arities) \
+ BOOST_PP_TUPLE_ELEM(3, 0, arities)
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_ARITY_required(arities) \
+ BOOST_PP_TUPLE_ELEM(3, 1, arities)
+/**/
+
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/repetition/enum_trailing.hpp>
+#include <boost/preprocessor/tuple/rem.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC0(r, n, elem, data) \
+ (( \
+ BOOST_PP_TUPLE_ELEM(3, 2, data) \
+ , BOOST_PP_TUPLE_REM(BOOST_PP_TUPLE_ELEM(3, 0, data)) elem \
+ BOOST_PP_ENUM_TRAILING( \
+ BOOST_PP_SUB( \
+ BOOST_PP_TUPLE_ELEM(3, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(3, 0, data) \
+ ) \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC0_DUMMY_ELEM \
+ , ~ \
+ ) \
+ ))
+/**/
+
+#include <boost/parameter/aux_/preprocessor/impl/for_each.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_AUX( \
+ r, arity, max_arity, spec, xform \
+) \
+ BOOST_PARAMETER_AUX_PP_FOR_EACH_R( \
+ r \
+ , arity \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN_ARGS(spec) \
+ , ( \
+ arity \
+ , max_arity \
+ , xform(BOOST_PARAMETER_AUX_PP_FLATTEN_QUALIFIER(spec)) \
+ ) \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC0 \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_optional(r, arities, spec) \
+ BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_AUX( \
+ r \
+ , BOOST_PP_CAT( \
+ BOOST_PARAMETER_AUX_PP_FLATTEN_ARITY_ \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN_QUALIFIER(spec) \
+ )(arities) \
+ , BOOST_PP_TUPLE_ELEM(3, 2, arities) \
+ , spec \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN_IDENTITY \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_required(r, arities, spec) \
+ BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_optional(r, arities, spec)
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_deduced_M(r, arities, n, spec) \
+ BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_AUX( \
+ r \
+ , BOOST_PP_CAT( \
+ BOOST_PARAMETER_AUX_PP_FLATTEN_ARITY_ \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN_QUALIFIER(spec) \
+ )(arities) \
+ , BOOST_PP_TUPLE_ELEM(3, 2, arities) \
+ , spec \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_AS_DEDUCED \
+ )
+/**/
+
+#include <boost/preprocessor/seq/for_each_i.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_deduced(r, arities, spec) \
+ BOOST_PP_SEQ_FOR_EACH_I_R( \
+ r \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_deduced_M \
+ , arities \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN_ARGS(spec) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC(r, arities, spec) \
+ BOOST_PP_CAT( \
+ BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC_ \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN_QUALIFIER(spec) \
+ )(r, arities, spec)
+/**/
+
+#include <boost/preprocessor/seq/for_each.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FLATTEN( \
+ opt_arity, req_arity, wanted_arity, specs \
+) \
+ BOOST_PP_SEQ_FOR_EACH( \
+ BOOST_PARAMETER_AUX_PP_FLATTEN_SPEC \
+ , (opt_arity, req_arity, wanted_arity) \
+ , specs \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/for_each.hpp b/boost/parameter/aux_/preprocessor/impl/for_each.hpp
new file mode 100644
index 0000000000..b6ece207f2
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/for_each.hpp
@@ -0,0 +1,152 @@
+// Copyright Daniel Wallin 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FOR_EACH_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FOR_EACH_HPP
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_head_aux2(x, y) (x, y), ~
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_head_aux3(x, y, z) (x, y, z), ~
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_head_aux4(x, y, z, u) (x, y, z, u), ~
+
+#define \
+BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux_BOOST_PARAMETER_AUX_PP_FOR_EACH_END_S
+/**/
+
+#include <boost/preprocessor/detail/split.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_SPLIT_FIRST(x) \
+ BOOST_PP_SPLIT(0, x)
+/**/
+
+#include <boost/preprocessor/cat.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_head(n, x) \
+ BOOST_PP_SPLIT( \
+ 0 \
+ , BOOST_PP_CAT(BOOST_PARAMETER_AUX_PP_FOR_EACH_head_aux, n) x \
+ )
+/**/
+
+#include <boost/preprocessor/facilities/is_empty.hpp>
+#include <boost/preprocessor/logical/not.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux_check(x) \
+ BOOST_PP_NOT(BOOST_PP_IS_EMPTY( \
+ BOOST_PP_CAT(BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux_, x) \
+ )), ~
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux2(x, y) \
+ BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux_check(x)
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux3(x, y, z) \
+ BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux_check(x)
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux4(x, y, z, u) \
+ BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux_check(x)
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux0(n, x) \
+ BOOST_PP_CAT(BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux, n) x
+/**/
+
+#include <boost/preprocessor/tuple/elem.hpp>
+
+#if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_pred(r, state) \
+ BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_SPLIT_FIRST( \
+ BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux0( \
+ BOOST_PP_TUPLE_ELEM(5, 3, state) \
+ , BOOST_PP_TUPLE_ELEM(5, 0, state) \
+ ) \
+ )
+/**/
+
+#else // !(BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC())
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_pred(r, state) \
+ BOOST_PP_SPLIT( \
+ 0 \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_pred_aux0( \
+ BOOST_PP_TUPLE_ELEM(5, 3, state) \
+ , BOOST_PP_TUPLE_ELEM(5, 0, state) \
+ ) \
+ )
+/**/
+
+#endif // BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_op(r, state) \
+ ( \
+ BOOST_PP_TUPLE_EAT(BOOST_PP_TUPLE_ELEM(5, 3, state)) \
+ BOOST_PP_TUPLE_ELEM(5, 0, state) \
+ , BOOST_PP_TUPLE_ELEM(5, 1, state) \
+ , BOOST_PP_TUPLE_ELEM(5, 2, state) \
+ , BOOST_PP_TUPLE_ELEM(5, 3, state) \
+ , BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(5, 4, state)) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_macro(r, state) \
+ BOOST_PP_TUPLE_ELEM(5, 2, state)( \
+ r \
+ , BOOST_PP_TUPLE_ELEM(5, 4, state) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_head( \
+ BOOST_PP_TUPLE_ELEM(5, 3, state) \
+ , BOOST_PP_TUPLE_ELEM(5, 0, state) \
+ ) \
+ , BOOST_PP_TUPLE_ELEM(5, 1, state) \
+ )
+/**/
+
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_build_end_sentinel(z, n, text) \
+ BOOST_PP_COMMA_IF(n) BOOST_PARAMETER_AUX_PP_FOR_EACH_END_S
+/**/
+
+#include <boost/preprocessor/repetition/repeat.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_build_end_sentinel_tuple(arity) \
+ ( \
+ BOOST_PP_REPEAT( \
+ arity, BOOST_PARAMETER_AUX_PP_FOR_EACH_build_end_sentinel, _ \
+ ) \
+ )
+/**/
+
+#include <boost/preprocessor/repetition/for.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH_R(r, arity, list, data, macro) \
+ BOOST_PP_CAT(BOOST_PP_FOR_, r)( \
+ (list \
+ BOOST_PARAMETER_AUX_PP_FOR_EACH_build_end_sentinel_tuple(arity) \
+ , data \
+ , macro \
+ , arity \
+ , 0 \
+ ) \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_pred \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_op \
+ , BOOST_PARAMETER_AUX_PP_FOR_EACH_macro \
+ )
+/**/
+
+#include <boost/preprocessor/repetition/deduce_r.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_FOR_EACH(arity, list, data, macro) \
+ BOOST_PARAMETER_AUX_PP_FOR_EACH_R( \
+ BOOST_PP_DEDUCE_R(), arity, list, data, macro \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/forwarding_overloads.hpp b/boost/parameter/aux_/preprocessor/impl/forwarding_overloads.hpp
new file mode 100644
index 0000000000..f5eb7ab797
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/forwarding_overloads.hpp
@@ -0,0 +1,509 @@
+// Copyright Daniel Wallin 2006.
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PREPROCESSOR_IMPL_FORWARDING_OVERLOADS_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FORWARDING_OVERLOADS_HPP
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+#include <boost/preprocessor/cat.hpp>
+
+// Expands to a forwarding parameter for a constructor or forwarding function.
+#define BOOST_PARAMETER_FUNCTION_ARG_TYPE_Z(z, n, type_prefix) \
+ BOOST_PP_CAT(type_prefix, n)&&
+/**/
+
+#include <utility>
+
+// Expands to an argument passed from a forwarding function to the front-end
+// implementation function, or from a constructor to its delegate.
+#define BOOST_PARAMETER_FUNCTION_FORWARD_PARAM_Z(z, n, type_prefix) \
+ ::std::forward<BOOST_PP_CAT(type_prefix, n)>(BOOST_PP_CAT(a, n))
+/**/
+
+#include <boost/parameter/aux_/preprocessor/impl/parenthesized_type.hpp>
+#include <boost/preprocessor/tuple/elem.hpp>
+
+// Expands to the default constructor, whose job is to pass an empty back to
+// the delegate constructor of the base class.
+#define BOOST_PARAMETER_CONSTRUCTOR_OVERLOAD_0_Z(z, n, data) \
+ inline BOOST_PP_TUPLE_ELEM(2, 0, data)() \
+ : BOOST_PARAMETER_PARENTHESIZED_TYPE(BOOST_PP_TUPLE_ELEM(2, 1, data))( \
+ BOOST_PP_CAT(constructor_parameters, __LINE__)()() \
+ ) \
+ { \
+ }
+/**/
+
+#include <boost/parameter/aux_/pp_impl/argument_pack.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/function_name.hpp>
+#include <boost/preprocessor/control/expr_if.hpp>
+
+// Expands to a 0-arity forwarding function, whose job is to pass an empty
+// pack to the front-end implementation function.
+#define BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_0_Z(z, n, data) \
+ BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(BOOST_PP_TUPLE_ELEM(4, 1, data)) \
+ inline BOOST_PARAMETER_FUNCTION_RESULT_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )< \
+ ::boost::parameter::aux::argument_pack< \
+ BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ ) \
+ >::type \
+ >::type \
+ BOOST_PARAMETER_MEMBER_FUNCTION_NAME(BOOST_PP_TUPLE_ELEM(3, 0, data))() \
+ BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 3, data), const) \
+ { \
+ return BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 2, data), this->) \
+ BOOST_PARAMETER_FUNCTION_IMPL_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )( \
+ BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )()() \
+ ); \
+ }
+/**/
+
+#include <boost/parameter/aux_/preprocessor/impl/function_forward_match.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+
+// Expands to a forwarding function, whose job is to consolidate its arguments
+// into a pack for the front-end implementation function to take in.
+#define BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_1_Z(z, n, data) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename ParameterArgumentType)> \
+ BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(BOOST_PP_TUPLE_ELEM(4, 1, data)) \
+ inline typename BOOST_PARAMETER_FUNCTION_RESULT_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )< \
+ typename ::boost::parameter::aux::argument_pack< \
+ BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ ) \
+ , BOOST_PP_CAT(BOOST_PP_ENUM_, z)( \
+ n \
+ , BOOST_PARAMETER_FUNCTION_ARG_TYPE_Z \
+ , ParameterArgumentType \
+ ) \
+ >::type \
+ >::type \
+ BOOST_PARAMETER_MEMBER_FUNCTION_NAME(BOOST_PP_TUPLE_ELEM(4, 0, data))( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, ParameterArgumentType, && a) \
+ BOOST_PARAMETER_FUNCTION_FORWARD_MATCH_Z( \
+ z \
+ , BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ ) \
+ , n \
+ , ParameterArgumentType \
+ ) \
+ ) BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 3, data), const) \
+ { \
+ return BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 2, data), this->) \
+ BOOST_PARAMETER_FUNCTION_IMPL_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )( \
+ BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )()( \
+ BOOST_PP_CAT(BOOST_PP_ENUM_, z)( \
+ n \
+ , BOOST_PARAMETER_FUNCTION_FORWARD_PARAM_Z \
+ , ParameterArgumentType \
+ ) \
+ ) \
+ ); \
+ }
+/**/
+
+#include <boost/preprocessor/comparison/equal.hpp>
+
+// Expands to a constructor whose job is to consolidate its arguments into a
+// pack for the delegate constructor of the base class to take in.
+#define BOOST_PARAMETER_CONSTRUCTOR_OVERLOAD_1_Z(z, n, data) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename ParameterArgumentType)> \
+ BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(n, 1), explicit) \
+ inline BOOST_PP_TUPLE_ELEM(2, 0, data)( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, ParameterArgumentType, && a) \
+ BOOST_PARAMETER_FUNCTION_FORWARD_MATCH_Z( \
+ z \
+ , BOOST_PP_CAT(constructor_parameters, __LINE__) \
+ , n \
+ , ParameterArgumentType \
+ ) \
+ ) : BOOST_PARAMETER_PARENTHESIZED_TYPE(BOOST_PP_TUPLE_ELEM(2, 1, data))( \
+ BOOST_PP_CAT(constructor_parameters, __LINE__)()( \
+ BOOST_PP_CAT(BOOST_PP_ENUM_, z)( \
+ n \
+ , BOOST_PARAMETER_FUNCTION_FORWARD_PARAM_Z \
+ , ParameterArgumentType \
+ ) \
+ ) \
+ ) \
+ { \
+ }
+/**/
+
+#include <boost/preprocessor/control/if.hpp>
+
+#define BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_Z(z, n, data) \
+ BOOST_PP_IF( \
+ n \
+ , BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_1_Z \
+ , BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_0_Z \
+ )(z, n, data)
+/**/
+
+#define BOOST_PARAMETER_CONSTRUCTOR_OVERLOAD_Z(z, n, data) \
+ BOOST_PP_IF( \
+ n \
+ , BOOST_PARAMETER_CONSTRUCTOR_OVERLOAD_1_Z \
+ , BOOST_PARAMETER_CONSTRUCTOR_OVERLOAD_0_Z \
+ )(z, n, data)
+/**/
+
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+// Helper macro for BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS.
+#define BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS_AUX(nm, impl, r, is_m, c) \
+ BOOST_PP_REPEAT_FROM_TO( \
+ BOOST_PP_TUPLE_ELEM(2, 0, r) \
+ , BOOST_PP_TUPLE_ELEM(2, 1, r) \
+ , BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_Z \
+ , ( \
+ nm \
+ , impl \
+ , BOOST_PP_IF( \
+ BOOST_PARAMETER_MEMBER_FUNCTION_IS_STATIC(nm) \
+ , 0 \
+ , is_m \
+ ) \
+ , c \
+ ) \
+ )
+/**/
+
+// Helper macro for BOOST_PARAMETER_CONSTRUCTOR_OVERLOADS.
+#define BOOST_PARAMETER_CONSTRUCTOR_OVERLOADS_AUX(class_, base, range) \
+ BOOST_PP_REPEAT_FROM_TO( \
+ BOOST_PP_TUPLE_ELEM(2, 0, range) \
+ , BOOST_PP_TUPLE_ELEM(2, 1, range) \
+ , BOOST_PARAMETER_CONSTRUCTOR_OVERLOAD_Z \
+ , (class_, base) \
+ )
+/**/
+
+#include <boost/parameter/aux_/preprocessor/impl/arity_range.hpp>
+
+// Expands to the layer of forwarding functions for the function with the
+// specified name, whose arguments determine the range of arities.
+#define BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS(name, impl, a, is_m, c) \
+ BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS_AUX( \
+ name, impl, BOOST_PARAMETER_ARITY_RANGE(a), is_m, c \
+ )
+/**/
+
+// Expands to the layer of forwarding functions for the constructor in the
+// specified class, whose arguments determine the range of arities.
+#define BOOST_PARAMETER_CONSTRUCTOR_OVERLOADS(class_, base, args) \
+ BOOST_PARAMETER_CONSTRUCTOR_OVERLOADS_AUX( \
+ class_, base, BOOST_PARAMETER_ARITY_RANGE(args) \
+ )
+/**/
+
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+#include <boost/parameter/aux_/preprocessor/impl/parenthesized_type.hpp>
+#include <boost/preprocessor/seq/seq.hpp>
+#include <boost/preprocessor/tuple/elem.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+// Expands to the default constructor, whose job is to pass an empty argument
+// pack back to the delegate constructor of the base class.
+#define BOOST_PARAMETER_DEFAULT_CONSTRUCTOR(z, n, seq) \
+ inline \
+ BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)))() \
+ : BOOST_PARAMETER_PARENTHESIZED_TYPE( \
+ BOOST_PP_TUPLE_ELEM( \
+ 2, 1, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ )(BOOST_PP_CAT(constructor_parameters, __LINE__)()()) \
+ { \
+ }
+/**/
+
+#include <boost/parameter/aux_/pp_impl/argument_pack.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/function_name.hpp>
+#include <boost/preprocessor/control/expr_if.hpp>
+
+// Expands to a 0-arity forwarding function, whose job is to pass an empty
+// argument pack to the front-end implementation function.
+#define BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_0_ARITY(z, n, seq) \
+ BOOST_PARAMETER_MEMBER_FUNCTION_STATIC( \
+ BOOST_PP_TUPLE_ELEM( \
+ 4, 1, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ ) \
+ inline BOOST_PARAMETER_FUNCTION_RESULT_NAME( \
+ BOOST_PP_TUPLE_ELEM( \
+ 4, 1, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ , BOOST_PP_TUPLE_ELEM( \
+ 4, 3, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ )< \
+ ::boost::parameter::aux::argument_pack< \
+ BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME( \
+ BOOST_PP_TUPLE_ELEM( \
+ 4, 1, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ , BOOST_PP_TUPLE_ELEM( \
+ 4, 3, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ ) \
+ >::type \
+ >::type \
+ BOOST_PARAMETER_MEMBER_FUNCTION_NAME( \
+ BOOST_PP_TUPLE_ELEM( \
+ 4, 0, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ )() BOOST_PP_EXPR_IF( \
+ BOOST_PP_TUPLE_ELEM( \
+ 4, 3, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ , const \
+ ) \
+ { \
+ return BOOST_PP_EXPR_IF( \
+ BOOST_PP_TUPLE_ELEM( \
+ 4, 2, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ , this-> \
+ ) BOOST_PARAMETER_FUNCTION_IMPL_NAME( \
+ BOOST_PP_TUPLE_ELEM( \
+ 4, 1, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ , BOOST_PP_TUPLE_ELEM( \
+ 4, 3, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ )( \
+ BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME( \
+ BOOST_PP_TUPLE_ELEM( \
+ 4, 1, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ , BOOST_PP_TUPLE_ELEM( \
+ 4, 3, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ )()() \
+ ); \
+ }
+/**/
+
+#include <boost/parameter/aux_/preprocessor/binary_seq_to_args.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/function_forward_match.hpp>
+#include <boost/preprocessor/comparison/equal.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/seq/size.hpp>
+
+// Expands to a constructor whose job is to consolidate its arguments into a
+// pack for the delegate constructor of the base class to take in. Each
+// element in BOOST_PP_SEQ_TAIL(seq) determines the const-ness of the
+// corresponding argument.
+#define BOOST_PARAMETER_CONSTRUCTOR_OVERLOAD_R(r, seq) \
+ template < \
+ BOOST_PP_ENUM_PARAMS( \
+ BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_TAIL(seq)) \
+ , typename ParameterArgumentType \
+ ) \
+ > \
+ BOOST_PP_EXPR_IF( \
+ BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_TAIL(seq)), 1) \
+ , explicit \
+ ) \
+ inline BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_SEQ_HEAD(seq))( \
+ BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARGS( \
+ BOOST_PP_SEQ_TAIL(seq), (ParameterArgumentType)(a) \
+ ) \
+ BOOST_PARAMETER_FUNCTION_FORWARD_MATCH( \
+ BOOST_PP_CAT(constructor_parameters, __LINE__) \
+ , BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_TAIL(seq)) \
+ , ParameterArgumentType \
+ ) \
+ ) : BOOST_PARAMETER_PARENTHESIZED_TYPE( \
+ BOOST_PP_TUPLE_ELEM(2, 1, BOOST_PP_SEQ_HEAD(seq)) \
+ )( \
+ BOOST_PP_CAT(constructor_parameters, __LINE__)()( \
+ BOOST_PP_ENUM_PARAMS( \
+ BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_TAIL(seq)), a \
+ ) \
+ ) \
+ ) \
+ { \
+ }
+/**/
+
+// Expands to a forwarding function, whose job is to consolidate its arguments
+// into a pack for the front-end implementation function to take in. Each
+// element in BOOST_PP_SEQ_TAIL(seq) determines the const-ness of the
+// corresponding argument.
+#define BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_R(r, seq) \
+ template < \
+ BOOST_PP_ENUM_PARAMS( \
+ BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_TAIL(seq)) \
+ , typename ParameterArgumentType \
+ ) \
+ > \
+ BOOST_PARAMETER_MEMBER_FUNCTION_STATIC( \
+ BOOST_PP_TUPLE_ELEM(4, 1, BOOST_PP_SEQ_HEAD(seq)) \
+ ) \
+ inline typename BOOST_PARAMETER_FUNCTION_RESULT_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, BOOST_PP_SEQ_HEAD(seq)) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, BOOST_PP_SEQ_HEAD(seq)) \
+ )< \
+ typename ::boost::parameter::aux::argument_pack< \
+ BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, BOOST_PP_SEQ_HEAD(seq)) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, BOOST_PP_SEQ_HEAD(seq)) \
+ ) \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARGS( \
+ BOOST_PP_SEQ_TAIL(seq), (ParameterArgumentType) \
+ ) \
+ >::type \
+ >::type \
+ BOOST_PARAMETER_MEMBER_FUNCTION_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 0, BOOST_PP_SEQ_HEAD(seq)) \
+ )( \
+ BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARGS( \
+ BOOST_PP_SEQ_TAIL(seq), (ParameterArgumentType)(a) \
+ ) \
+ BOOST_PARAMETER_FUNCTION_FORWARD_MATCH( \
+ BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, BOOST_PP_SEQ_HEAD(seq)) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, BOOST_PP_SEQ_HEAD(seq)) \
+ ) \
+ , BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_TAIL(seq)) \
+ , ParameterArgumentType \
+ ) \
+ ) BOOST_PP_EXPR_IF( \
+ BOOST_PP_TUPLE_ELEM(4, 3, BOOST_PP_SEQ_HEAD(seq)), const \
+ ) \
+ { \
+ return BOOST_PP_EXPR_IF( \
+ BOOST_PP_TUPLE_ELEM(4, 2, BOOST_PP_SEQ_HEAD(seq)) \
+ , this-> \
+ ) BOOST_PARAMETER_FUNCTION_IMPL_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, BOOST_PP_SEQ_HEAD(seq)) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, BOOST_PP_SEQ_HEAD(seq)) \
+ )( \
+ BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, BOOST_PP_SEQ_HEAD(seq)) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, BOOST_PP_SEQ_HEAD(seq)) \
+ )()( \
+ BOOST_PP_ENUM_PARAMS( \
+ BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_TAIL(seq)), a \
+ ) \
+ ) \
+ ); \
+ }
+/**/
+
+#include <boost/parameter/aux_/preprocessor/binary_seq_for_each.hpp>
+#include <boost/preprocessor/control/if.hpp>
+
+// Expands to all constructors that take in n arguments. Enables
+// BOOST_PARAMETER_CONSTRUCTOR_OVERLOADS_AUX to use
+// BOOST_PARAMETER_CONSTRUCTOR_OVERLOAD_Z within BOOST_PP_REPEAT_FROM_TO.
+#define BOOST_PARAMETER_CONSTRUCTOR_OVERLOAD_Z(z, n, data) \
+ BOOST_PP_IF( \
+ n \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_Z \
+ , BOOST_PARAMETER_DEFAULT_CONSTRUCTOR \
+ )(z, n, (BOOST_PARAMETER_CONSTRUCTOR_OVERLOAD_R)(data))
+/**/
+
+// Expands to all forwarding functions that take in n arguments. Enables
+// BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS_AUX to use
+// BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_Z within BOOST_PP_REPEAT_FROM_TO.
+#define BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_Z(z, n, data) \
+ BOOST_PP_IF( \
+ n \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_Z \
+ , BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_0_ARITY \
+ )(z, n, (BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_R)(data))
+/**/
+
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+// Helper macro for BOOST_PARAMETER_CONSTRUCTOR_OVERLOADS.
+#define BOOST_PARAMETER_CONSTRUCTOR_OVERLOADS_AUX(class_, base, range) \
+ BOOST_PP_REPEAT_FROM_TO( \
+ BOOST_PP_TUPLE_ELEM(2, 0, range) \
+ , BOOST_PP_TUPLE_ELEM(2, 1, range) \
+ , BOOST_PARAMETER_CONSTRUCTOR_OVERLOAD_Z \
+ , (class_, base) \
+ )
+/**/
+
+// Helper macro for BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS.
+#define BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS_AUX(nm, impl, r, is_m, c) \
+ BOOST_PP_REPEAT_FROM_TO( \
+ BOOST_PP_TUPLE_ELEM(2, 0, r) \
+ , BOOST_PP_TUPLE_ELEM(2, 1, r) \
+ , BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOAD_Z \
+ , ( \
+ nm \
+ , impl \
+ , BOOST_PP_IF( \
+ BOOST_PARAMETER_MEMBER_FUNCTION_IS_STATIC(impl) \
+ , 0 \
+ , is_m \
+ ) \
+ , c \
+ ) \
+ )
+/**/
+
+#include <boost/parameter/aux_/preprocessor/impl/arity_range.hpp>
+
+// Expands to the layer of forwarding functions for the constructor in the
+// specified class, whose arguments determine the range of arities.
+#define BOOST_PARAMETER_CONSTRUCTOR_OVERLOADS(class_, base, args) \
+ BOOST_PARAMETER_CONSTRUCTOR_OVERLOADS_AUX( \
+ class_ \
+ , base \
+ , BOOST_PARAMETER_ARITY_RANGE(args) \
+ )
+/**/
+
+// Expands to the layer of forwarding functions for the function with the
+// specified name, whose arguments determine the range of arities.
+#define BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS(name, impl, a, is_m, c) \
+ BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS_AUX( \
+ name \
+ , impl \
+ , BOOST_PARAMETER_ARITY_RANGE(a) \
+ , is_m \
+ , c \
+ )
+/**/
+
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/function_cast.hpp b/boost/parameter/aux_/preprocessor/impl/function_cast.hpp
new file mode 100644
index 0000000000..2c40a25798
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/function_cast.hpp
@@ -0,0 +1,730 @@
+// Copyright Daniel Wallin 2006.
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_CAST_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_CAST_HPP
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Handles possible implicit casts. Used by preprocessor.hpp
+ // to normalize user input.
+ //
+ // cast<void*>::execute() is identity
+ // cast<void*(X)>::execute() is identity
+ // cast<void(X)>::execute() casts to X
+ //
+ // preprocessor.hpp uses this like this:
+ //
+ // #define X(value, predicate)
+ // cast<void predicate>::execute(value)
+ //
+ // X(something, *)
+ // X(something, *(predicate))
+ // X(something, (int))
+ template <typename VoidExpr, typename Args>
+ struct cast;
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/use_default_tag.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T, typename B>
+ inline ::boost::parameter::aux::use_default_tag
+ forward(::boost::parameter::aux::use_default_tag)
+ {
+ return ::boost::parameter::aux::use_default_tag();
+ }
+}}} // namespace boost::parameter::aux
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Args>
+ struct cast<void*,Args>
+ {
+ template <typename T, typename B>
+ struct apply
+ {
+ typedef typename ::boost::mpl
+ ::if_<B,T,::boost::mpl::true_>::type type;
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename T, typename B>
+ using fn = ::boost::mp11::mp_if<B,T,::boost::mp11::mp_true>;
+#endif
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/void.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Predicate, typename Args>
+ struct cast<void*(Predicate),Args>
+ : ::boost::parameter::aux::cast<void*,Args>
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/mpl/placeholders.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // This is a hack used in cast<> to turn the user supplied type,
+ // which may or may not be a placeholder expression, into one,
+ // so that it will be properly evaluated by mpl::apply.
+ template <typename T, typename Dummy = ::boost::mpl::_1>
+ struct as_placeholder_expr
+ {
+ typedef T type;
+ };
+}}} // namespace boost::parameter::aux
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/list.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Target, typename Source, typename Args>
+ struct apply_target_fn
+ {
+ using type = ::boost::mp11
+ ::mp_apply_q<Target,::boost::mp11::mp_list<Source,Args> >;
+ };
+}}} // namespace boost::parameter::aux
+
+#endif
+
+#include <boost/mpl/apply.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/parameter/aux_/has_nested_template_fn.hpp>
+#include <type_traits>
+#else
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Target, typename Source, typename Args>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using is_target_same_as_source = ::std::is_same<
+ typename ::std::remove_const<
+ typename ::std::remove_reference<
+ typename ::boost::mp11::mp_if<
+ ::boost::parameter::aux::has_nested_template_fn<Target>
+ , ::boost::parameter::aux
+ ::apply_target_fn<Target,Source,Args>
+ , ::boost::mpl::apply2<
+ ::boost::parameter::aux::as_placeholder_expr<Target>
+ , Source
+ , Args
+ >
+ >::type
+ >::type
+ >::type
+ , typename ::std::remove_const<Source>::type
+ >;
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ struct is_target_same_as_source
+ : ::boost::mpl::if_<
+ ::boost::is_same<
+ typename ::boost::remove_const<
+ typename ::boost::remove_reference<
+ typename ::boost::mpl::apply2<
+ ::boost::parameter::aux
+ ::as_placeholder_expr<Target>
+ , Source
+ , Args
+ >::type
+ >::type
+ >::type
+ , typename ::boost::remove_const<Source>::type
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >::type
+ {
+ };
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}}} // namespace boost::parameter::aux
+
+#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/is_const.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Covers the case where is_convertible<Source,Target> but not
+ // is_same<Source,Target>. Use cases are covered
+ // by test/normalize_argument_types.cpp
+ template <typename Source, typename Target>
+ class cast_convert
+ {
+ typedef ::boost::parameter::aux::cast_convert<Source,Target> _self;
+
+ public:
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = typename ::boost::mp11::mp_if<
+ ::std::is_const<Source>
+ , ::std::add_const<Target>
+ , ::std::remove_const<Target>
+ >::type;
+#else
+ typedef typename boost::mpl::eval_if<
+ ::boost::is_const<Source>
+ , ::boost::add_const<Target>
+ , ::boost::remove_const<Target>
+ >::type type;
+#endif
+
+ private:
+ inline static typename _self::type
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ _copy(typename ::std::remove_const<Target>::type value)
+#else
+ _copy(typename ::boost::remove_const<Target>::type value)
+#endif
+ {
+ return value;
+ }
+
+ public:
+ inline static typename _self::type evaluate(Source&& source)
+ {
+ return _self::_copy(source);
+ }
+ };
+
+ template <typename Target, typename Source, typename Args>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using cast_impl = ::std::remove_reference<
+ typename ::boost::mp11::mp_if<
+ ::boost::parameter::aux::has_nested_template_fn<Target>
+ , ::boost::parameter::aux
+ ::is_target_same_as_source<Target,Source,Args>
+ , ::boost::mpl::apply2<
+ ::boost::parameter::aux::as_placeholder_expr<Target>
+ , Source
+ , Args
+ >
+ >::type
+ >;
+#else
+ struct cast_impl
+ : ::boost::remove_reference<
+ typename ::boost::mpl::apply2<
+ ::boost::parameter::aux::as_placeholder_expr<Target>
+ , Source
+ , Args
+ >::type
+ >
+ {
+ };
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}}} // namespace boost::parameter::aux
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Target, typename Args>
+ struct cast<void(Target),Args>
+ {
+ template <typename T, typename B>
+ struct apply
+ {
+ typedef typename ::boost::mpl::eval_if<
+ B
+ , ::boost::mpl::eval_if<
+ ::boost::parameter::aux
+ ::is_target_same_as_source<Target,T,Args>
+ , ::boost::mpl::identity<T>
+ , ::boost::parameter::aux::cast_impl<Target,T,Args>
+ >
+ , ::boost::parameter::aux
+ ::is_target_same_as_source<Target,T,Args>
+ >::type type;
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename T, typename B>
+ using fn = typename ::boost::mp11::mp_if<
+ B
+ , ::boost::mp11::mp_if<
+ ::boost::parameter::aux
+ ::is_target_same_as_source<Target,T,Args>
+ , ::boost::mp11::mp_identity<T>
+ , ::boost::parameter::aux::cast_impl<Target,T,Args>
+ >
+ , ::boost::parameter::aux
+ ::is_target_same_as_source<Target,T,Args>
+ >::type;
+#endif
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/value_type.hpp>
+
+#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mpl/apply_wrap.hpp>
+#endif
+
+// Expands to the target type of the argument as indicated by the predicate.
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_FUNCTION_CAST_T(tag, predicate, args) \
+ ::boost::mp11::mp_apply_q< \
+ ::boost::parameter::aux::cast<void predicate, args> \
+ , ::boost::mp11::mp_list< \
+ typename ::boost::parameter::value_type< \
+ args \
+ , tag \
+ , ::boost::parameter::aux::use_default_tag \
+ >::type \
+ , ::boost::mp11::mp_true \
+ > \
+ >
+/**/
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_FUNCTION_CAST_T(tag, predicate, args) \
+ typename ::boost::mpl::apply_wrap2< \
+ ::boost::parameter::aux::cast<void predicate, args> \
+ , typename ::boost::parameter::value_type< \
+ args \
+ , tag \
+ , ::boost::parameter::aux::use_default_tag \
+ >::type \
+ , ::boost::mpl::true_ \
+ >::type
+/**/
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+// Expands to boost::mpl::true_ if and only if the argument's source and
+// target types are the same.
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_FUNCTION_CAST_B(tag, predicate, args) \
+ ::boost::mp11::mp_apply_q< \
+ ::boost::parameter::aux::cast<void predicate, args> \
+ , ::boost::mp11::mp_list< \
+ typename ::boost::parameter::value_type< \
+ args \
+ , tag \
+ , ::boost::parameter::aux::use_default_tag \
+ >::type \
+ , ::boost::mp11::mp_false \
+ > \
+ >
+/**/
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_FUNCTION_CAST_B(tag, predicate, args) \
+ typename ::boost::mpl::apply_wrap2< \
+ ::boost::parameter::aux::cast<void predicate, args> \
+ , typename ::boost::parameter::value_type< \
+ args \
+ , tag \
+ , ::boost::parameter::aux::use_default_tag \
+ >::type \
+ , ::boost::mpl::false_ \
+ >::type
+/**/
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+#include <boost/core/enable_if.hpp>
+#include <utility>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // If the source and target types are not the same,
+ // then perform an implicit conversion.
+ template <typename Target, typename B, typename Source>
+ inline typename ::boost::lazy_disable_if<
+ B
+ , ::boost::parameter::aux::cast_convert<Source,Target>
+ >::type
+ forward(Source&& source)
+ {
+ return ::boost::parameter::aux::cast_convert<Source,Target>
+ ::evaluate(::std::forward<Source>(source));
+ }
+
+ // If the source and target types are the same,
+ // then simply forward the argument.
+ // However, treat rvalue references to scalars as const lvalue references.
+ template <typename T, typename B>
+ inline typename ::boost::enable_if<B,T const&>::type forward(T const& t)
+ {
+ return t;
+ }
+
+ template <typename T, typename B>
+ inline typename ::boost::enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ B
+ , ::boost::mp11::mp_if<
+ ::std::is_const<T>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ , ::boost::mp11::mp_false
+ >
+#else
+ typename ::boost::mpl::eval_if<
+ B
+ , ::boost::mpl::if_<
+ ::boost::is_const<T>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::false_
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , T&
+ >::type
+ forward(T& t)
+ {
+ return t;
+ }
+}}} // namespace boost::parameter::aux
+
+#include <boost/type_traits/is_scalar.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T, typename B>
+ inline typename ::boost::enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ B
+ , ::boost::mp11::mp_if<
+ ::std::is_scalar<T>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ , ::boost::mp11::mp_false
+ >
+#else
+ typename ::boost::mpl::eval_if<
+ B
+ , ::boost::mpl::if_<
+ ::boost::is_scalar<T>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::false_
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , T const&&
+ >::type
+ forward(T const&& t)
+ {
+ return static_cast<T const&&>(t);
+ }
+
+ template <typename T, typename B>
+ inline typename ::boost::enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ B
+ , ::boost::mp11::mp_if<
+ ::std::is_scalar<T>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ , ::boost::mp11::mp_false
+ >
+#else
+ typename ::boost::mpl::eval_if<
+ B
+ , ::boost::mpl::if_<
+ ::boost::is_scalar<T>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::false_
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , T&&
+ >::type
+ forward(T&& t)
+ {
+ return ::std::forward<T>(t);
+ }
+}}} // namespace boost::parameter::aux
+
+#elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+#define BOOST_PARAMETER_FUNCTION_CAST_T(value_t, predicate, args) value_t
+#define BOOST_PARAMETER_FUNCTION_CAST_B(value, predicate, args) value
+#else // no perfect forwarding support and no Borland workarounds needed
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Handles possible implicit casts. Used by preprocessor.hpp
+ // to normalize user input.
+ //
+ // cast<void*>::execute() is identity
+ // cast<void*(X)>::execute() is identity
+ // cast<void(X)>::execute() casts to X
+ //
+ // preprocessor.hpp uses this like this:
+ //
+ // #define X(value, predicate)
+ // cast<void predicate>::execute(value)
+ //
+ // X(something, *)
+ // X(something, *(predicate))
+ // X(something, (int))
+ template <typename VoidExpr, typename Args>
+ struct cast;
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/use_default_tag.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Args>
+ struct cast<void*,Args>
+ {
+ template <typename T>
+ struct apply
+ {
+ typedef T& type;
+ };
+
+ inline static ::boost::parameter::aux::use_default_tag
+ execute(::boost::parameter::aux::use_default_tag)
+ {
+ return ::boost::parameter::aux::use_default_tag();
+ }
+
+ template <typename U>
+ inline static U& execute(U& value)
+ {
+ return value;
+ }
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/aux_/void.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Predicate, typename Args>
+#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580))
+ struct cast< ::boost::parameter::aux::voidstar(Predicate),Args>
+#else
+ struct cast<void*(Predicate),Args>
+#endif
+ : ::boost::parameter::aux::cast<void*,Args>
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/mpl/placeholders.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // This is a hack used in cast<> to turn the user supplied type,
+ // which may or may not be a placeholder expression, into one,
+ // so that it will be properly evaluated by mpl::apply.
+ template <typename T, typename Dummy = ::boost::mpl::_1>
+ struct as_placeholder_expr
+ {
+ typedef T type;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/mpl/apply.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Target, typename Source, typename Args>
+ struct is_target_same_as_source
+ : ::boost::mpl::if_<
+ ::boost::is_same<
+ typename ::boost::remove_const<
+ typename ::boost::remove_reference<
+ typename ::boost::mpl::apply2<
+ ::boost::parameter::aux
+ ::as_placeholder_expr<Target>
+ , Source
+ , Args
+ >::type
+ >::type
+ >::type
+ , typename ::boost::remove_const<Source>::type
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >::type
+ {
+ };
+
+ template <
+ typename Target
+ , typename Source
+ , typename Args
+ , typename Enable = ::boost::parameter::aux
+ ::is_target_same_as_source<Target,Source,Args>
+ >
+ struct cast_impl
+ {
+ typedef Source& type;
+
+ inline static Source& evaluate(Source& value)
+ {
+ return value;
+ }
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/add_lvalue_reference.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Covers the case where is_convertible<Source,Target> but not
+ // is_same<Source,Target>. Use cases are covered
+ // by test/normalize_argument_types.cpp
+ template <typename Source, typename Target>
+ class cast_convert
+ {
+ typedef ::boost::parameter::aux::cast_convert<Source,Target> _self;
+
+ public:
+ typedef typename ::boost::add_lvalue_reference<
+ typename ::boost::add_const<Target>::type
+ >::type type;
+
+ private:
+ template <typename U>
+ inline static typename _self::type _mod_const(U const& u)
+ {
+ return u;
+ }
+
+ inline static Target _copy(Target value)
+ {
+ return value;
+ }
+
+ public:
+ inline static typename _self::type evaluate(Source& source)
+ {
+ return _self::_mod_const(_self::_copy(source));
+ }
+ };
+
+ template <typename Target, typename Source, typename Args>
+ struct cast_impl<Target,Source,Args,::boost::mpl::false_>
+ : ::boost::parameter::aux::cast_convert<
+ Source,
+ typename ::boost::mpl::apply2<
+ ::boost::parameter::aux::as_placeholder_expr<Target>
+ , Source
+ , Args
+ >::type
+ >
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Target, typename Args>
+ struct cast<void(Target),Args>
+ {
+ template <typename T>
+ struct apply
+ {
+ typedef typename ::boost::mpl::eval_if<
+ ::boost::parameter::aux
+ ::is_target_same_as_source<Target,T,Args>
+ , ::boost::add_lvalue_reference<T>
+ , ::boost::parameter::aux::cast_impl<
+ Target
+ , T
+ , Args
+ , ::boost::mpl::false_
+ >
+ >::type type;
+ };
+
+ inline static ::boost::parameter::aux::use_default_tag
+ execute(::boost::parameter::aux::use_default_tag)
+ {
+ return ::boost::parameter::aux::use_default_tag();
+ }
+
+ template <typename U>
+ inline static typename ::boost::parameter::aux
+ ::cast_impl<Target,U const,Args>::type
+ execute(U const& value)
+ {
+ return ::boost::parameter::aux
+ ::cast_impl<Target,U const,Args>::evaluate(value);
+ }
+
+ template <typename U>
+ inline static typename ::boost::parameter::aux
+ ::cast_impl<Target,U,Args>::type
+ execute(U& value)
+ {
+ return ::boost::parameter::aux
+ ::cast_impl<Target,U,Args>::evaluate(value);
+ }
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/parameter/value_type.hpp>
+
+// Expands to the reference-qualified target type of the argument
+// as indicated by the predicate.
+#define BOOST_PARAMETER_FUNCTION_CAST_T(tag, predicate, args) \
+ typename ::boost::mpl::apply_wrap1< \
+ ::boost::parameter::aux::cast<void predicate, args> \
+ , typename ::boost::parameter::value_type< \
+ args \
+ , tag \
+ , ::boost::parameter::aux::use_default_tag \
+ >::type \
+ >::type
+/**/
+
+// Expands to the converted or passed-through value
+// as indicated by the predicate.
+#define BOOST_PARAMETER_FUNCTION_CAST_B(value, predicate, args) \
+ ::boost::parameter::aux::cast<void predicate, args>::execute(value)
+/**/
+
+#endif // perfect forwarding support, or Borland workarounds needed
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/function_dispatch_layer.hpp b/boost/parameter/aux_/preprocessor/impl/function_dispatch_layer.hpp
new file mode 100644
index 0000000000..3c240d527c
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/function_dispatch_layer.hpp
@@ -0,0 +1,474 @@
+// Copyright Daniel Wallin 2006.
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_DISPATCH_LAYER_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_DISPATCH_LAYER_HPP
+
+#include <boost/preprocessor/cat.hpp>
+
+// Expands to keyword_tag_type for some keyword_tag.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_TYPE(keyword_tag) \
+ BOOST_PP_CAT(keyword_tag, _type)
+/**/
+
+// Expands to a template parameter for each dispatch function.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_TEMPLATE_ARG(r, macro, arg) \
+ , typename BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_TYPE(macro(arg))
+/**/
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+// Expands to a forwarding parameter for a dispatch function.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_DEFN(r, macro, arg) \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_TYPE(macro(arg))&& macro(arg)
+/**/
+
+#include <utility>
+
+// Expands to an argument passed from one dispatch function to the next.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_FWD(r, macro, arg) \
+ , ::std::forward< \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_TYPE(macro(arg)) \
+ >(macro(arg))
+/**/
+
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+// Expands to a forwarding parameter for a dispatch function. The parameter
+// type stores its const-ness.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_DEFN(r, macro, arg) \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_TYPE(macro(arg))& macro(arg)
+/**/
+
+#include <boost/parameter/aux_/as_lvalue.hpp>
+
+// Expands to an argument passed from one dispatch function to the next.
+// Explicit forwarding takes the form of forcing the argument to be an lvalue.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_FWD(r, macro, arg) \
+ , ::boost::parameter::aux::as_lvalue(macro(arg))
+/**/
+
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+
+#include <boost/parameter/aux_/preprocessor/impl/argument_specs.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/split_args.hpp>
+#include <boost/preprocessor/seq/for_each.hpp>
+#include <boost/preprocessor/seq/first_n.hpp>
+
+// Iterates through all required arguments and the first n optional arguments,
+// passing each argument to the specified macro.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT(macro, n, split_args) \
+ BOOST_PP_SEQ_FOR_EACH( \
+ macro \
+ , BOOST_PARAMETER_FN_ARG_NAME \
+ , BOOST_PARAMETER_SPLIT_ARG_REQ_SEQ(split_args) \
+ ) \
+ BOOST_PP_SEQ_FOR_EACH( \
+ macro \
+ , BOOST_PARAMETER_FN_ARG_NAME \
+ , BOOST_PP_SEQ_FIRST_N( \
+ n, BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ(split_args) \
+ ) \
+ )
+/**/
+
+#include <boost/parameter/aux_/preprocessor/impl/function_dispatch_tuple.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/function_name.hpp>
+#include <boost/preprocessor/control/if.hpp>
+
+// Produces a name for the dispatch functions.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, n) \
+ BOOST_PP_CAT( \
+ BOOST_PP_CAT( \
+ BOOST_PP_IF( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x) \
+ , boost_param_dispatch_const_ \
+ , boost_param_dispatch_ \
+ ) \
+ , BOOST_PP_CAT(BOOST_PP_CAT(n, boost_), __LINE__) \
+ ) \
+ , BOOST_PARAMETER_MEMBER_FUNCTION_NAME( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \
+ ) \
+ )
+/**/
+
+// Expands to the template parameter list of the dispatch function with all
+// required and first n optional parameters; also extracts the static keyword
+// if present.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \
+ template < \
+ typename ResultType, typename Args \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_TEMPLATE_ARG \
+ , n \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ > BOOST_PARAMETER_MEMBER_FUNCTION_STATIC( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \
+ )
+/**/
+
+#include <boost/parameter/aux_/use_default_tag.hpp>
+#include <boost/preprocessor/control/expr_if.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+
+// Expands to the result type, name, parenthesized list of all required and
+// n optional parameters, and const-ness of the dispatch function; the bit
+// value b determines whether or not this dispatch function takes in
+// boost::parameter::aux::use_default_tag as its last parameter.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, b1, b2) \
+ ResultType BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, b1)( \
+ ResultType(*)(), Args const& args, long \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_DEFN \
+ , n \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ BOOST_PP_COMMA_IF(b2) \
+ BOOST_PP_EXPR_IF(b2, ::boost::parameter::aux::use_default_tag) \
+ ) BOOST_PP_EXPR_IF(BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x), const)
+/**/
+
+// Expands to a forward declaration of the dispatch function that takes in
+// all required and the first n optional parameters, but not
+// boost::parameter::aux::use_default_tag.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_FWD_DECL_0_Z(z, n, x) \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, 0, 0);
+/**/
+
+// Expands to a forward declaration of the dispatch function that takes in
+// all required parameters, the first n optional parameters, and
+// boost::parameter::aux::use_default_tag.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_FWD_DECL_1_Z(z, n, x) \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, 0, 1);
+/**/
+
+#include <boost/preprocessor/seq/elem.hpp>
+
+// Expands to the default value of the (n + 1)th optional parameter.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_DEFAULT_AUX(n, s_args) \
+ BOOST_PARAMETER_FN_ARG_DEFAULT( \
+ BOOST_PP_SEQ_ELEM(n, BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ(s_args)) \
+ )
+/**/
+
+#include <boost/parameter/keyword.hpp>
+
+// Expands to the assignment portion which binds the default value to the
+// (n + 1)th optional parameter before composing it with the argument-pack
+// parameter passed in to the n-th dispatch function.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_DEFAULT(n, s_args, tag_ns) \
+ ::boost::parameter::keyword< \
+ tag_ns::BOOST_PARAMETER_FN_ARG_NAME( \
+ BOOST_PP_SEQ_ELEM(n, BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ(s_args)) \
+ ) \
+ >::instance = BOOST_PARAMETER_FUNCTION_DISPATCH_DEFAULT_AUX(n, s_args)
+/**/
+
+#include <boost/parameter/aux_/preprocessor/impl/function_cast.hpp>
+
+// Takes in the arg tuple (name, pred) and the tag namespace.
+// Extracts the corresponding required argument from the pack.
+// This form enables BOOST_PARAMETER_FUNCTION_DISPATCH_LAYER to use it
+// from within BOOST_PP_SEQ_FOR_EACH.
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+// The boost::parameter::aux::forward wrapper is necessary to transmit the
+// target type to the next dispatch function. Otherwise, the argument will
+// retain its original type. -- Cromwell D. Enage
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_CAST_R(r, tag_ns, arg) \
+ , ::boost::parameter::aux::forward< \
+ BOOST_PARAMETER_FUNCTION_CAST_T( \
+ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \
+ , BOOST_PARAMETER_FN_ARG_PRED(arg) \
+ , Args \
+ ) \
+ , BOOST_PARAMETER_FUNCTION_CAST_B( \
+ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \
+ , BOOST_PARAMETER_FN_ARG_PRED(arg) \
+ , Args \
+ ) \
+ >( \
+ args[ \
+ ::boost::parameter::keyword< \
+ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \
+ >::instance \
+ ] \
+ )
+/**/
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+// The explicit type cast is necessary to transmit the target type to the next
+// dispatch function. Otherwise, the argument will retain its original type.
+// -- Cromwell D. Enage
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_CAST_R(r, tag_ns, arg) \
+ , BOOST_PARAMETER_FUNCTION_CAST_T( \
+ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \
+ , BOOST_PARAMETER_FN_ARG_PRED(arg) \
+ , Args \
+ )( \
+ args[ \
+ ::boost::parameter::keyword< \
+ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \
+ >::instance \
+ ] \
+ )
+/**/
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+
+// Takes in the arg tuple (name, pred, default) and the tag namespace.
+// Extracts the corresponding optional argument from the pack if specified,
+// otherwise temporarily passes use_default_tag() to the dispatch functions.
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+// The boost::parameter::aux::forward wrapper is necessary to transmit the
+// target type to the next dispatch function. Otherwise, the argument will
+// retain its original type. -- Cromwell D. Enage
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_OPT_ARG_CAST(arg, tag_ns) \
+ ::boost::parameter::aux::forward< \
+ BOOST_PARAMETER_FUNCTION_CAST_T( \
+ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \
+ , BOOST_PARAMETER_FN_ARG_PRED(arg) \
+ , Args \
+ ) \
+ , BOOST_PARAMETER_FUNCTION_CAST_B( \
+ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \
+ , BOOST_PARAMETER_FN_ARG_PRED(arg) \
+ , Args \
+ ) \
+ >( \
+ args[ \
+ ::boost::parameter::keyword< \
+ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \
+ >::instance || ::boost::parameter::aux::use_default_tag() \
+ ] \
+ )
+/**/
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_OPT_ARG_CAST(arg, tag_ns) \
+ BOOST_PARAMETER_FUNCTION_CAST_B( \
+ args[ \
+ ::boost::parameter::keyword< \
+ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \
+ >::instance || ::boost::parameter::aux::use_default_tag() \
+ ] \
+ , BOOST_PARAMETER_FN_ARG_PRED(arg) \
+ , Args \
+ )
+/**/
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+
+#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
+
+// Expands to three dispatch functions that take in all required parameters
+// and the first n optional parameters. The third dispatch function bears
+// the same name as the first but takes in use_default_tag as the last
+// parameter. The second dispatch function bears a different name from the
+// other two.
+//
+// x is a tuple:
+//
+// (name, split_args, is_const, tag_namespace)
+//
+// Where name is the base name of the functions, and split_args is a tuple:
+//
+// (required_count, required_args, optional_count, required_args)
+//
+// The first dispatch function queries args if it has bound the (n + 1)th
+// optional parameter to a user-defined argument. If so, then it forwards
+// its own arguments followed by the user-defined argument to the dispatch
+// function that takes in all required parameters and the first (n + 1)
+// optional parameters, but not use_default_tag. Otherwise, it forwards
+// its own arguments to the third dispatch function.
+//
+// The third dispatch function appends the default value of the (n + 1)th
+// optional parameter to its copy of args. Then it forwards this copy, all
+// required parameters, and the first n (not n + 1) optional parameters to
+// the second dispatch function.
+//
+// The second dispatch function forwards its arguments, then the (n + 1)th
+// optional parameter that it extracts from args, to the other-named dispatch
+// function that takes in all required parameters and the first (n + 1)
+// optional parameters, but not use_default_tag.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_OVERLOAD_Z(z, n, x) \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \
+ inline BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, 0, 0) \
+ { \
+ return BOOST_PP_EXPR_IF( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_IS_MEMBER(x) \
+ , this-> \
+ ) BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, 0)( \
+ static_cast<ResultType(*)()>(BOOST_PARAMETER_AUX_PP_NULLPTR) \
+ , args \
+ , 0L \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_FWD \
+ , n \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_OPT_ARG_CAST( \
+ BOOST_PP_SEQ_ELEM( \
+ n \
+ , BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ ) \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_TAG_NAMESPACE(x) \
+ ) \
+ ); \
+ } \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \
+ inline BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, 1, 0) \
+ { \
+ return BOOST_PP_EXPR_IF( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_IS_MEMBER(x) \
+ , this-> \
+ ) BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, 0)( \
+ static_cast<ResultType(*)()>(BOOST_PARAMETER_AUX_PP_NULLPTR) \
+ , args \
+ , 0L \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_FWD \
+ , n \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ , args[ \
+ ::boost::parameter::keyword< \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_TAG_NAMESPACE(x):: \
+ BOOST_PARAMETER_FN_ARG_NAME( \
+ BOOST_PP_SEQ_ELEM( \
+ n \
+ , BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ ) \
+ ) \
+ >::instance \
+ ] \
+ ); \
+ } \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \
+ inline BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, 0, 1) \
+ { \
+ return BOOST_PP_EXPR_IF( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_IS_MEMBER(x) \
+ , this-> \
+ ) BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, 1)( \
+ static_cast<ResultType(*)()>(BOOST_PARAMETER_AUX_PP_NULLPTR) \
+ , (args \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_DEFAULT( \
+ n \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_TAG_NAMESPACE(x) \
+ ) \
+ ) \
+ , 0L \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_FWD \
+ , n \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ ); \
+ }
+/**/
+
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+// x is a tuple:
+//
+// (base_name, split_args, is_member, is_const, tag_namespace)
+//
+// Generates all dispatch functions for the function named base_name. Each
+// dispatch function that takes in n optional parameters passes the default
+// value of the (n + 1)th optional parameter to the next dispatch function.
+// The last dispatch function is the back-end implementation, so only the
+// header is generated: the user is expected to supply the body.
+//
+// Also generates the front-end implementation function, which uses
+// BOOST_PARAMETER_FUNCTION_CAST to extract each argument from the argument
+// pack.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_LAYER(fwd_decl, x) \
+ BOOST_PP_IF(fwd_decl, BOOST_PP_REPEAT_FROM_TO, BOOST_PP_TUPLE_EAT(4))( \
+ 0 \
+ , BOOST_PP_INC( \
+ BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ ) \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_FWD_DECL_0_Z \
+ , x \
+ ) \
+ BOOST_PP_IF(fwd_decl, BOOST_PP_REPEAT_FROM_TO, BOOST_PP_TUPLE_EAT(4))( \
+ 0 \
+ , BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_FWD_DECL_1_Z \
+ , x \
+ ) \
+ template <typename Args> BOOST_PARAMETER_MEMBER_FUNCTION_STATIC( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \
+ ) inline typename BOOST_PARAMETER_FUNCTION_RESULT_NAME( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x) \
+ )<Args>::type BOOST_PARAMETER_FUNCTION_IMPL_NAME( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x) \
+ )(Args const& args) \
+ BOOST_PP_EXPR_IF(BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x), const) \
+ { \
+ return BOOST_PP_EXPR_IF( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_IS_MEMBER(x) \
+ , this-> \
+ ) BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, 0)( \
+ static_cast< \
+ typename BOOST_PARAMETER_FUNCTION_RESULT_NAME( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x) \
+ )<Args>::type(*)() \
+ >(BOOST_PARAMETER_AUX_PP_NULLPTR) \
+ , args \
+ , 0L \
+ BOOST_PP_SEQ_FOR_EACH( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_CAST_R \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_TAG_NAMESPACE(x) \
+ , BOOST_PARAMETER_SPLIT_ARG_REQ_SEQ( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ ) \
+ ); \
+ } \
+ BOOST_PP_REPEAT_FROM_TO( \
+ 0 \
+ , BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ , BOOST_PARAMETER_FUNCTION_DISPATCH_OVERLOAD_Z \
+ , x \
+ ) \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL( \
+ BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ , x \
+ ) \
+ inline BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN( \
+ BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT( \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ ) \
+ , x \
+ , 0 \
+ , 0 \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/function_dispatch_tuple.hpp b/boost/parameter/aux_/preprocessor/impl/function_dispatch_tuple.hpp
new file mode 100644
index 0000000000..b24c898e69
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/function_dispatch_tuple.hpp
@@ -0,0 +1,33 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_DISPATCH_TUPLE_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_DISPATCH_TUPLE_HPP
+
+#include <boost/preprocessor/tuple/elem.hpp>
+
+// Accessor macros for the input tuple to the dispatch macros.
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \
+ BOOST_PP_TUPLE_ELEM(5, 0, x)
+/**/
+
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \
+ BOOST_PP_TUPLE_ELEM(5, 1, x)
+/**/
+
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_IS_MEMBER(x) \
+ BOOST_PP_TUPLE_ELEM(5, 2, x)
+/**/
+
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x) \
+ BOOST_PP_TUPLE_ELEM(5, 3, x)
+/**/
+
+#define BOOST_PARAMETER_FUNCTION_DISPATCH_TAG_NAMESPACE(x) \
+ BOOST_PP_TUPLE_ELEM(5, 4, x)
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/function_forward_match.hpp b/boost/parameter/aux_/preprocessor/impl/function_forward_match.hpp
new file mode 100644
index 0000000000..3b452ed960
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/function_forward_match.hpp
@@ -0,0 +1,43 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_FORWARD_MATCH_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_FORWARD_MATCH_HPP
+
+#include <boost/parameter/config.hpp>
+
+#if !defined(BOOST_NO_SFINAE) && \
+ !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
+
+#include <boost/parameter/aux_/pp_impl/match.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+
+// Expands to an extra argument that is well-formed
+// iff all Args... satisfy the requirements set by params.
+#define BOOST_PARAMETER_FUNCTION_FORWARD_MATCH(params, n, prefix) \
+ , typename ::boost::parameter::aux::match< \
+ params BOOST_PP_ENUM_TRAILING_PARAMS(n, prefix) \
+ >::type = params()
+/**/
+
+#define BOOST_PARAMETER_FUNCTION_FORWARD_MATCH_Z(z, params, n, prefix) \
+ , typename ::boost::parameter::aux::match< \
+ params BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, prefix) \
+ >::type = params()
+/**/
+
+#else // SFINAE/Borland workarounds needed.
+
+#define BOOST_PARAMETER_FUNCTION_FORWARD_MATCH(params, n, prefix) \
+ , params = params()
+/**/
+
+#define BOOST_PARAMETER_FUNCTION_FORWARD_MATCH_Z(z, params, n, prefix) \
+ , params = params()
+/**/
+
+#endif
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/function_name.hpp b/boost/parameter/aux_/preprocessor/impl/function_name.hpp
new file mode 100644
index 0000000000..af5d194c49
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/function_name.hpp
@@ -0,0 +1,152 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_NAME_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_NAME_HPP
+
+#define BOOST_PARAMETER_MEMBER_FUNCTION_CHECK_STATIC_static ()
+/**/
+
+#include <boost/parameter/aux_/preprocessor/is_nullary.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+#define BOOST_PARAMETER_MEMBER_FUNCTION_IS_STATIC(name) \
+ BOOST_PARAMETER_IS_NULLARY( \
+ BOOST_PP_CAT(BOOST_PARAMETER_MEMBER_FUNCTION_CHECK_STATIC_, name) \
+ )
+/**/
+
+#include <boost/preprocessor/seq/seq.hpp>
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+
+// Workaround for MSVC preprocessor.
+//
+// When stripping static from "static f", msvc will produce " f". The leading
+// whitespace doesn't go away when pasting the token with something else, so
+// this thing is a hack to strip the whitespace.
+#define BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_static (
+/**/
+
+#define BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_AUX(name) \
+ BOOST_PP_CAT(BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_, name))
+/**/
+
+#define BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC(name) \
+ BOOST_PP_SEQ_HEAD( \
+ BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_AUX(name) \
+ )
+/**/
+
+#else
+
+#define BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_static
+/**/
+
+#define BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC(name) \
+ BOOST_PP_CAT(BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_, name)
+/**/
+
+#endif // MSVC workarounds needed
+
+#include <boost/preprocessor/control/expr_if.hpp>
+
+#define BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(name) \
+ BOOST_PP_EXPR_IF( \
+ BOOST_PARAMETER_MEMBER_FUNCTION_IS_STATIC(name), static \
+ )
+/**/
+
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+#define BOOST_PARAMETER_MEMBER_FUNCTION_NAME(name) \
+ BOOST_PP_IF( \
+ BOOST_PARAMETER_MEMBER_FUNCTION_IS_STATIC(name) \
+ , BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC \
+ , name BOOST_PP_TUPLE_EAT(1) \
+ )(name)
+/**/
+
+// Produces a name for a parameter specification for the function named base.
+#define BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME(base, is_const) \
+ BOOST_PP_CAT( \
+ BOOST_PP_CAT( \
+ BOOST_PP_IF( \
+ is_const \
+ , boost_param_parameters_const_ \
+ , boost_param_parameters_ \
+ ) \
+ , __LINE__ \
+ ) \
+ , BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base) \
+ )
+/**/
+
+// Produces a name for a result type metafunction for the no-spec function
+// named base.
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(base, is_const) \
+ BOOST_PP_CAT( \
+ BOOST_PP_CAT( \
+ BOOST_PP_IF( \
+ is_const \
+ , boost_param_no_spec_result_const_ \
+ , boost_param_no_spec_result_ \
+ ) \
+ , __LINE__ \
+ ) \
+ , BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base) \
+ )
+/**/
+
+// Produces a name for a result type metafunction for the function named base.
+#define BOOST_PARAMETER_FUNCTION_RESULT_NAME(base, is_const) \
+ BOOST_PP_CAT( \
+ BOOST_PP_CAT( \
+ BOOST_PP_IF( \
+ is_const \
+ , boost_param_result_const_ \
+ , boost_param_result_ \
+ ) \
+ , __LINE__ \
+ ) \
+ , BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base) \
+ )
+/**/
+
+// Produces a name for the implementation function to which the no-spec
+// function named base forwards its result type and argument pack.
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_NAME(base, is_const) \
+ BOOST_PP_CAT( \
+ BOOST_PP_CAT( \
+ BOOST_PP_IF( \
+ is_const \
+ , boost_param_no_spec_impl_const \
+ , boost_param_no_spec_impl \
+ ) \
+ , __LINE__ \
+ ) \
+ , BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base) \
+ )
+/**/
+
+// Can't do boost_param_impl_ ## basee
+// because base might start with an underscore.
+// daniel: what? how is that relevant? the reason for using CAT()
+// is to make sure base is expanded. i'm not sure we need to here,
+// but it's more stable to do it.
+#define BOOST_PARAMETER_FUNCTION_IMPL_NAME(base, is_const) \
+ BOOST_PP_CAT( \
+ BOOST_PP_CAT( \
+ BOOST_PP_IF(is_const, boost_param_impl_const, boost_param_impl) \
+ , __LINE__ \
+ ) \
+ , BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base) \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/no_spec_overloads.hpp b/boost/parameter/aux_/preprocessor/impl/no_spec_overloads.hpp
new file mode 100644
index 0000000000..345e408dd4
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/no_spec_overloads.hpp
@@ -0,0 +1,331 @@
+// Copyright Cromwell D. Enage 2018.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_NO_SPEC_OVERLOADS_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_NO_SPEC_OVERLOADS_HPP
+
+#include <boost/parameter/aux_/preprocessor/impl/function_name.hpp>
+
+// Defines the no-spec implementation function header.
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_HEAD(name, is_const) \
+ template <typename ResultType, typename Args> \
+ BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(name) ResultType \
+ BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_NAME( \
+ name, is_const \
+ )(ResultType(*)(), Args const& args)
+/**/
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+#include <boost/parameter/aux_/preprocessor/impl/parenthesized_return_type.hpp>
+
+// Expands to the result metafunction for the specified no-spec function.
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION_HEAD(result, name, is_const) \
+ template <typename TaggedArg0, typename ...TaggedArgs> \
+ using BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(name, is_const) \
+ = typename BOOST_PARAMETER_PARENTHESIZED_RETURN_TYPE(result);
+/**/
+#else
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION_HEAD(result, name, is_const) \
+ template <typename TaggedArg0, typename ...TaggedArgs> \
+ struct BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(name, is_const) \
+ : BOOST_PARAMETER_PARENTHESIZED_RETURN_TYPE(result) \
+ { \
+ };
+/**/
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+#include <boost/parameter/compose.hpp>
+#include <boost/parameter/are_tagged_arguments.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/parenthesized_type.hpp>
+#include <boost/core/enable_if.hpp>
+
+// Exapnds to a variadic constructor that is enabled if and only if all its
+// arguments are tagged arguments. The enclosing class must inherit from the
+// specified base class, which in turn must implement a constructor that takes
+// in the argument pack that this one passes on.
+#define BOOST_PARAMETER_NO_SPEC_CONSTRUCTOR(class_, base) \
+ template < \
+ typename TaggedArg0 \
+ , typename ...TaggedArgs \
+ , typename = typename ::boost::enable_if< \
+ ::boost::parameter \
+ ::are_tagged_arguments<TaggedArg0,TaggedArgs...> \
+ >::type \
+ > inline explicit \
+ class_(TaggedArg0 const& arg0, TaggedArgs const&... args) \
+ : BOOST_PARAMETER_PARENTHESIZED_TYPE(base)( \
+ ::boost::parameter::compose(arg0, args...) \
+ ) \
+ { \
+ }
+/**/
+
+// Exapnds to a variadic constructor that is enabled if and only if all its
+// arguments are tagged arguments. The specified function must be able to
+// take in the argument pack that this constructor passes on.
+#define BOOST_PARAMETER_NO_SPEC_NO_BASE_CONSTRUCTOR(class_, func) \
+ template < \
+ typename TaggedArg0 \
+ , typename ...TaggedArgs \
+ , typename = typename ::boost::enable_if< \
+ ::boost::parameter \
+ ::are_tagged_arguments<TaggedArg0,TaggedArgs...> \
+ >::type \
+ > inline explicit \
+ class_(TaggedArg0 const& arg0, TaggedArgs const&... args) \
+ { \
+ func(::boost::parameter::compose(arg0, args...)); \
+ }
+/**/
+
+#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
+#include <boost/preprocessor/control/expr_if.hpp>
+
+// Exapnds to a variadic function that is enabled if and only if
+// all its arguments are tagged arguments.
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD(name, impl, is_m, c) \
+ template <typename TaggedArg0, typename ...TaggedArgs> \
+ BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(impl) \
+ inline typename ::boost::lazy_enable_if< \
+ ::boost::parameter \
+ ::are_tagged_arguments<TaggedArg0,TaggedArgs...> \
+ , BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME( \
+ impl, c \
+ )<TaggedArg0,TaggedArgs...> \
+ >::type BOOST_PARAMETER_MEMBER_FUNCTION_NAME(name) \
+ (TaggedArg0 const& arg0, TaggedArgs const&... args) \
+ BOOST_PP_EXPR_IF(c, const) \
+ { \
+ return BOOST_PP_EXPR_IF(is_m, this->) \
+ BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_NAME(impl, c)( \
+ static_cast< \
+ typename BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME( \
+ impl, c \
+ )<TaggedArg0,TaggedArgs...>::type(*)() \
+ >(BOOST_PARAMETER_AUX_PP_NULLPTR) \
+ , ::boost::parameter::compose(arg0, args...) \
+ ); \
+ }
+/**/
+
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/parenthesized_return_type.hpp>
+#include <boost/preprocessor/facilities/intercept.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+
+// Expands to the result metafunction for the specified no-spec function.
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION_HEAD(result, name, is_const) \
+ template < \
+ BOOST_PP_ENUM_BINARY_PARAMS( \
+ BOOST_PARAMETER_COMPOSE_MAX_ARITY \
+ , typename TaggedArg \
+ , = ::boost::parameter::void_ BOOST_PP_INTERCEPT \
+ ) \
+ > \
+ struct BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(name, is_const) \
+ : BOOST_PARAMETER_PARENTHESIZED_RETURN_TYPE(result) \
+ { \
+ };
+/**/
+
+#include <boost/parameter/compose.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/parenthesized_type.hpp>
+#include <boost/preprocessor/comparison/equal.hpp>
+#include <boost/preprocessor/control/expr_if.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/tuple/elem.hpp>
+
+#if defined(BOOST_NO_SFINAE)
+
+// Exapnds to a tagged-argument constructor overload that passes the argument
+// pack to the base class delegate constructor.
+#define BOOST_PARAMETER_NO_SPEC_CONSTRUCTOR_OVERLOAD_Z(z, n, data) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)> \
+ BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(n, 1), explicit) inline \
+ BOOST_PP_TUPLE_ELEM(2, 0, data)( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& arg) \
+ ) : BOOST_PARAMETER_PARENTHESIZED_TYPE(BOOST_PP_TUPLE_ELEM(2, 1, data))( \
+ ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, arg)) \
+ ) \
+ { \
+ }
+/**/
+
+// Exapnds to a tagged-argument constructor overload that passes the argument
+// pack to the delegate function.
+#define BOOST_PARAMETER_NO_SPEC_NO_BASE_CONSTRUCTOR_OVERLOAD_Z(z, n, data) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)> \
+ BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(n, 1), explicit) inline \
+ BOOST_PP_TUPLE_ELEM(2, 0, data)( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& a) \
+ ) \
+ { \
+ BOOST_PP_TUPLE_ELEM(2, 1, data)( \
+ ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, a)) \
+ ); \
+ }
+/**/
+
+#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
+
+// Exapnds to a tagged-argument function overload.
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD_Z(z, n, data) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)> \
+ BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(BOOST_PP_TUPLE_ELEM(4, 1, data)) \
+ inline typename BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )<BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)>::type \
+ BOOST_PARAMETER_MEMBER_FUNCTION_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 0, data) \
+ )(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& arg)) \
+ BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 3, data), const) \
+ { \
+ return BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 2, data), this->) \
+ BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )( \
+ static_cast< \
+ typename BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )<BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)>::type(*)() \
+ >(BOOST_PARAMETER_AUX_PP_NULLPTR) \
+ , ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, arg)) \
+ ); \
+ }
+/**/
+
+#else // !defined(BOOST_NO_SFINAE)
+
+#include <boost/parameter/are_tagged_arguments.hpp>
+#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
+#include <boost/core/enable_if.hpp>
+
+// Exapnds to a tagged-argument constructor overload that passes the argument
+// pack to the base class delegate constructor. This constructor is enabled
+// if and only if all its arguments are tagged arguments.
+#define BOOST_PARAMETER_NO_SPEC_CONSTRUCTOR_OVERLOAD_Z(z, n, data) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)> \
+ BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(n, 1), explicit) inline \
+ BOOST_PP_TUPLE_ELEM(2, 0, data)( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& arg) \
+ , typename ::boost::enable_if< \
+ ::boost::parameter::are_tagged_arguments< \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg) \
+ > \
+ >::type* = BOOST_PARAMETER_AUX_PP_NULLPTR \
+ ) : BOOST_PARAMETER_PARENTHESIZED_TYPE(BOOST_PP_TUPLE_ELEM(2, 1, data))( \
+ ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, arg)) \
+ ) \
+ { \
+ }
+/**/
+
+// Exapnds to a tagged-argument constructor overload that passes the argument
+// pack to the delegate function. This constructor is enabled if and only if
+// all its arguments are tagged arguments.
+#define BOOST_PARAMETER_NO_SPEC_NO_BASE_CONSTRUCTOR_OVERLOAD_Z(z, n, data) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)> \
+ BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(n, 1), explicit) inline \
+ BOOST_PP_TUPLE_ELEM(2, 0, data)( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& a) \
+ , typename ::boost::enable_if< \
+ ::boost::parameter::are_tagged_arguments< \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg) \
+ > \
+ >::type* = BOOST_PARAMETER_AUX_PP_NULLPTR \
+ ) \
+ { \
+ BOOST_PP_TUPLE_ELEM(2, 1, data)( \
+ ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, a)) \
+ ); \
+ }
+/**/
+
+// Exapnds to a function overload that is enabled if and only if
+// all its arguments are tagged arguments.
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD_Z(z, n, data) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)> \
+ BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(BOOST_PP_TUPLE_ELEM(4, 1, data)) \
+ inline typename ::boost::lazy_enable_if< \
+ ::boost::parameter \
+ ::are_tagged_arguments<BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)> \
+ , BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )<BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)> \
+ >::type BOOST_PARAMETER_MEMBER_FUNCTION_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 0, data) \
+ )(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& arg)) \
+ BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 3, data), const) \
+ { \
+ return BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 2, data), this->) \
+ BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )( \
+ static_cast< \
+ typename BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME( \
+ BOOST_PP_TUPLE_ELEM(4, 1, data) \
+ , BOOST_PP_TUPLE_ELEM(4, 3, data) \
+ )<BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)>::type(*)() \
+ >(BOOST_PARAMETER_AUX_PP_NULLPTR) \
+ , ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, arg)) \
+ ); \
+ }
+/**/
+
+#endif // BOOST_NO_SFINAE
+
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+// Emulates a variadic constructor that is enabled if and only if all its
+// arguments are tagged arguments. The enclosing class must inherit from the
+// specified base class, which in turn must implement a constructor that takes
+// in the argument pack that this one passes on.
+#define BOOST_PARAMETER_NO_SPEC_CONSTRUCTOR(class_, base) \
+ BOOST_PP_REPEAT_FROM_TO( \
+ 1 \
+ , BOOST_PP_INC(BOOST_PARAMETER_COMPOSE_MAX_ARITY) \
+ , BOOST_PARAMETER_NO_SPEC_CONSTRUCTOR_OVERLOAD_Z \
+ , (class_, base) \
+ )
+/**/
+
+// Emulates a variadic constructor that is enabled if and only if all its
+// arguments are tagged arguments. The specified function must be able to
+// take in the argument pack that this constructor passes on.
+#define BOOST_PARAMETER_NO_SPEC_NO_BASE_CONSTRUCTOR(class_, func) \
+ BOOST_PP_REPEAT_FROM_TO( \
+ 1 \
+ , BOOST_PP_INC(BOOST_PARAMETER_COMPOSE_MAX_ARITY) \
+ , BOOST_PARAMETER_NO_SPEC_NO_BASE_CONSTRUCTOR_OVERLOAD_Z \
+ , (class_, func) \
+ )
+/**/
+
+// Emulates a variadic function that is enabled if and only if
+// all its arguments are tagged arguments.
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD(name, impl, is_m, c) \
+ BOOST_PP_REPEAT_FROM_TO( \
+ 1 \
+ , BOOST_PP_INC(BOOST_PARAMETER_COMPOSE_MAX_ARITY) \
+ , BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD_Z \
+ , (name, impl, is_m, c) \
+ )
+/**/
+
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/parenthesized_return_type.hpp b/boost/parameter/aux_/preprocessor/impl/parenthesized_return_type.hpp
new file mode 100644
index 0000000000..6bd8a62951
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/parenthesized_return_type.hpp
@@ -0,0 +1,122 @@
+// Copyright Cromwell D. Enage 2019.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_PARENTHESIZED_RETURN_TYPE_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_PARENTHESIZED_RETURN_TYPE_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ // A metafunction that transforms void(*)(T) -> identity<T>
+ template <typename UnaryFunctionPointer>
+ struct unaryfunptr_return_type;
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/utility.hpp>
+#else
+#include <boost/mpl/identity.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Arg>
+ struct unaryfunptr_return_type<void(*)(Arg)>
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_identity<Arg>;
+#else
+ typedef ::boost::mpl::identity<Arg> type;
+#endif
+ };
+
+ template <>
+ struct unaryfunptr_return_type<void(*)(void)>
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_identity<void>;
+#else
+ typedef ::boost::mpl::identity<void> type;
+#endif
+ };
+}}} // namespace boost::parameter::aux
+
+#if !defined(BOOST_NO_SFINAE)
+#include <boost/core/enable_if.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Pred, typename Ret>
+ struct unaryfunptr_return_type<void(*)(::boost::enable_if<Pred,Ret>)>
+ {
+ typedef ::boost::enable_if<Pred,Ret> type;
+ };
+
+ template <bool b, typename Ret>
+ struct unaryfunptr_return_type<void(*)(::boost::enable_if_c<b,Ret>)>
+ {
+ typedef ::boost::enable_if_c<b,Ret> type;
+ };
+
+ template <typename Pred, typename Ret>
+ struct unaryfunptr_return_type<void(*)(::boost::lazy_enable_if<Pred,Ret>)>
+ {
+ typedef ::boost::lazy_enable_if<Pred,Ret> type;
+ };
+
+ template <bool b, typename Ret>
+ struct unaryfunptr_return_type<void(*)(::boost::lazy_enable_if_c<b,Ret>)>
+ {
+ typedef ::boost::lazy_enable_if_c<b,Ret> type;
+ };
+
+ template <typename Pred, typename Ret>
+ struct unaryfunptr_return_type<void(*)(::boost::disable_if<Pred,Ret>)>
+ {
+ typedef ::boost::disable_if<Pred,Ret> type;
+ };
+
+ template <bool b, typename Ret>
+ struct unaryfunptr_return_type<void(*)(::boost::disable_if_c<b,Ret>)>
+ {
+ typedef ::boost::disable_if_c<b,Ret> type;
+ };
+
+ template <typename B, typename Ret>
+ struct unaryfunptr_return_type<void(*)(::boost::lazy_disable_if<B,Ret>)>
+ {
+ typedef ::boost::lazy_disable_if<B,Ret> type;
+ };
+
+ template <bool b, typename Ret>
+ struct unaryfunptr_return_type<void(*)(::boost::lazy_disable_if_c<b,Ret>)>
+ {
+ typedef ::boost::lazy_disable_if_c<b,Ret> type;
+ };
+}}} // namespace boost::parameter::aux
+
+#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
+#include <type_traits>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <bool b, typename Ret>
+ struct unaryfunptr_return_type<void(*)(::std::enable_if<b,Ret>)>
+ {
+ typedef ::std::enable_if<b,Ret> type;
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_NO_CXX11_HDR_TYPE_TRAITS
+#endif // BOOST_NO_SFINAE
+
+// A macro that takes a parenthesized C++ type name (T) and transforms it
+// into an un-parenthesized type expression equivalent to identity<T>.
+#define BOOST_PARAMETER_PARENTHESIZED_RETURN_TYPE(x) \
+ ::boost::parameter::aux::unaryfunptr_return_type< void(*)x >::type
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/parenthesized_type.hpp b/boost/parameter/aux_/preprocessor/impl/parenthesized_type.hpp
new file mode 100644
index 0000000000..f3d9ed9a90
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/parenthesized_type.hpp
@@ -0,0 +1,34 @@
+// Copyright David Abrahams 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_PARENTHESIZED_TYPE_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_PARENTHESIZED_TYPE_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ // A metafunction that transforms void(*)(T) -> T
+ template <typename UnaryFunctionPointer>
+ struct unaryfunptr_arg_type;
+
+ template <typename Arg>
+ struct unaryfunptr_arg_type<void(*)(Arg)>
+ {
+ typedef Arg type;
+ };
+
+ template <>
+ struct unaryfunptr_arg_type<void(*)(void)>
+ {
+ typedef void type;
+ };
+}}} // namespace boost::parameter::aux
+
+// A macro that takes a parenthesized C++ type name (T) and transforms it
+// into an un-parenthesized type expression equivalent to T.
+#define BOOST_PARAMETER_PARENTHESIZED_TYPE(x) \
+ ::boost::parameter::aux::unaryfunptr_arg_type< void(*)x >::type
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/specification.hpp b/boost/parameter/aux_/preprocessor/impl/specification.hpp
new file mode 100644
index 0000000000..d2a4638a83
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/specification.hpp
@@ -0,0 +1,109 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_SPECIFICATION_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_SPECIFICATION_HPP
+
+#include <boost/parameter/optional.hpp>
+
+// Helper macros for BOOST_PARAMETER_SPECIFICATION_ELEM_R.
+#define BOOST_PARAMETER_QUALIFIED_TAG_optional(tag) \
+ optional<tag
+/**/
+
+#include <boost/parameter/required.hpp>
+
+#define BOOST_PARAMETER_QUALIFIED_TAG_required(tag) \
+ required<tag
+/**/
+
+#include <boost/parameter/deduced.hpp>
+
+#define BOOST_PARAMETER_QUALIFIED_TAG_deduced_optional(tag) \
+ optional< ::boost::parameter::deduced<tag>
+/**/
+
+#define BOOST_PARAMETER_QUALIFIED_TAG_deduced_required(tag) \
+ required< ::boost::parameter::deduced<tag>
+/**/
+
+#include <boost/parameter/aux_/preprocessor/impl/argument_specs.hpp>
+#include <boost/parameter/config.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+
+#include <boost/parameter/aux_/use_default.hpp>
+
+#define BOOST_PARAMETER_SPECIFICATION_ELEM_R(r, tag_namespace, i, elem) \
+ BOOST_PP_COMMA_IF(i) ::boost::parameter::BOOST_PP_CAT( \
+ BOOST_PARAMETER_QUALIFIED_TAG_ \
+ , BOOST_PARAMETER_FN_ARG_QUALIFIER(elem) \
+ )(tag_namespace::BOOST_PARAMETER_FN_ARG_NAME(elem)) \
+ , ::boost::parameter::aux::use_default \
+ >
+/**/
+
+#else // !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+
+#include <boost/parameter/aux_/pp_impl/unwrap_predicate.hpp>
+
+// Expands to each boost::parameter::parameters<> element type.
+#define BOOST_PARAMETER_SPECIFICATION_ELEM_R(r, tag_namespace, i, elem) \
+ BOOST_PP_COMMA_IF(i) ::boost::parameter::BOOST_PP_CAT( \
+ BOOST_PARAMETER_QUALIFIED_TAG_ \
+ , BOOST_PARAMETER_FN_ARG_QUALIFIER(elem) \
+ )(tag_namespace::BOOST_PARAMETER_FN_ARG_NAME(elem)) \
+ , typename ::boost::parameter::aux::unwrap_predicate< \
+ void BOOST_PARAMETER_FN_ARG_PRED(elem) \
+ >::type \
+ >
+/**/
+
+#endif // Borland workarounds needed.
+
+#include <boost/parameter/parameters.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/function_name.hpp>
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/seq/for_each_i.hpp>
+
+// Expands to a boost::parameter::parameters<> specialization for the
+// function named base. Used by BOOST_PARAMETER_CONSTRUCTOR_AUX and
+// BOOST_PARAMETER_FUNCTION_HEAD for their respective ParameterSpec models.
+#define BOOST_PARAMETER_SPECIFICATION(tag_ns, base, split_args, is_const) \
+ template <typename BoostParameterDummy> \
+ struct BOOST_PP_CAT( \
+ BOOST_PP_CAT( \
+ BOOST_PP_IF( \
+ is_const \
+ , boost_param_params_const_ \
+ , boost_param_params_ \
+ ) \
+ , __LINE__ \
+ ) \
+ , BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base) \
+ ) : ::boost::parameter::parameters< \
+ BOOST_PP_SEQ_FOR_EACH_I( \
+ BOOST_PARAMETER_SPECIFICATION_ELEM_R, tag_ns, split_args \
+ ) \
+ > \
+ { \
+ }; \
+ typedef BOOST_PP_CAT( \
+ BOOST_PP_CAT( \
+ BOOST_PP_IF( \
+ is_const \
+ , boost_param_params_const_ \
+ , boost_param_params_ \
+ ) \
+ , __LINE__ \
+ ) \
+ , BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base) \
+ )<int>
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/impl/split_args.hpp b/boost/parameter/aux_/preprocessor/impl/split_args.hpp
new file mode 100644
index 0000000000..bfda33b393
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/split_args.hpp
@@ -0,0 +1,71 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_SPLIT_ARGS_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_SPLIT_ARGS_HPP
+
+#include <boost/preprocessor/tuple/elem.hpp>
+
+// Accessor macros for the split_args tuple.
+#define BOOST_PARAMETER_SPLIT_ARG_REQ_COUNT(x) BOOST_PP_TUPLE_ELEM(4, 0, x)
+#define BOOST_PARAMETER_SPLIT_ARG_REQ_SEQ(x) BOOST_PP_TUPLE_ELEM(4, 1, x)
+#define BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT(x) BOOST_PP_TUPLE_ELEM(4, 2, x)
+#define BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ(x) BOOST_PP_TUPLE_ELEM(4, 3, x)
+
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/seq/push_back.hpp>
+
+// Helper macros for BOOST_PARAMETER_FUNCTION_SPLIT_ARGS.
+#define BOOST_PARAMETER_FUNCTION_SPLIT_ARG_required(s_a, arg) \
+ ( \
+ BOOST_PP_INC(BOOST_PARAMETER_SPLIT_ARG_REQ_COUNT(s_a)) \
+ , BOOST_PP_SEQ_PUSH_BACK(BOOST_PARAMETER_SPLIT_ARG_REQ_SEQ(s_a), arg) \
+ , BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT(s_a) \
+ , BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ(s_a) \
+ )
+/**/
+
+#define BOOST_PARAMETER_FUNCTION_SPLIT_ARG_deduced_required(split_args, arg) \
+ BOOST_PARAMETER_FUNCTION_SPLIT_ARG_required(split_args, arg)
+/**/
+
+#define BOOST_PARAMETER_FUNCTION_SPLIT_ARG_optional(s_a, arg) \
+ ( \
+ BOOST_PARAMETER_SPLIT_ARG_REQ_COUNT(s_a) \
+ , BOOST_PARAMETER_SPLIT_ARG_REQ_SEQ(s_a) \
+ , BOOST_PP_INC(BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT(s_a)) \
+ , BOOST_PP_SEQ_PUSH_BACK(BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ(s_a), arg) \
+ )
+/**/
+
+#define BOOST_PARAMETER_FUNCTION_SPLIT_ARG_deduced_optional(split_args, arg) \
+ BOOST_PARAMETER_FUNCTION_SPLIT_ARG_optional(split_args, arg)
+/**/
+
+#include <boost/parameter/aux_/preprocessor/impl/argument_specs.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+#define BOOST_PARAMETER_FUNCTION_SPLIT_ARG(s, split_args, arg) \
+ BOOST_PP_CAT( \
+ BOOST_PARAMETER_FUNCTION_SPLIT_ARG_ \
+ , BOOST_PARAMETER_FN_ARG_QUALIFIER(arg) \
+ )(split_args, arg)
+/**/
+
+#include <boost/preprocessor/seq/fold_left.hpp>
+#include <boost/preprocessor/seq/seq.hpp>
+
+// Expands from the flattened BOOST_PARAMETER_FUNCTION et. al. arg sequence to
+// the tuple (required_count, required_args, optional_count, optional_args).
+#define BOOST_PARAMETER_FUNCTION_SPLIT_ARGS(args) \
+ BOOST_PP_SEQ_FOLD_LEFT( \
+ BOOST_PARAMETER_FUNCTION_SPLIT_ARG \
+ , (0, BOOST_PP_SEQ_NIL, 0, BOOST_PP_SEQ_NIL) \
+ , args \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/inc_binary_seq.hpp b/boost/parameter/aux_/preprocessor/inc_binary_seq.hpp
new file mode 100644
index 0000000000..9796e336a1
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/inc_binary_seq.hpp
@@ -0,0 +1,78 @@
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PREPROCESSOR_INC_BINARY_SEQ_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_INC_BINARY_SEQ_HPP
+
+#include <boost/preprocessor/seq/push_back.hpp>
+
+// This macro keeps the rest of the sequence if carry == 0.
+#define BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ_0(seq, element) \
+ (BOOST_PP_SEQ_PUSH_BACK(seq, element), 0)
+/**/
+
+#include <boost/preprocessor/control/iif.hpp>
+
+// This macro updates the rest of the sequence if carry == 1.
+#define BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ_1(seq, element) \
+ (BOOST_PP_SEQ_PUSH_BACK(seq, BOOST_PP_IIF(element, 0, 1)), element)
+/**/
+
+#include <boost/preprocessor/tuple/elem.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+// This macro maintains a tuple (seq, carry), where seq is the intermediate
+// result and carry is a flag that will unset upon finding an element == 0.
+#define BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ_OP(s, result_tuple, element) \
+ BOOST_PP_CAT( \
+ BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ_ \
+ , BOOST_PP_TUPLE_ELEM(2, 1, result_tuple) \
+ )(BOOST_PP_TUPLE_ELEM(2, 0, result_tuple), element)
+/**/
+
+// This macro keeps the sequence at its original length if carry == 0.
+#define BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ_IMPL_0(seq) seq
+/**/
+
+// This macro appends a zero to seq if carry == 1.
+#define BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ_IMPL_1(seq) \
+ BOOST_PP_SEQ_PUSH_BACK(seq, 0)
+/**/
+
+// This macro takes in the tuple (seq, carry), with carry indicating whether
+// or not seq originally contained all 1s. If so, then seq now contains all
+// 0s, and this macro pushes an extra 0 before expanding to the new sequence.
+// Otherwise, this macro expands to seq as is.
+#define BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ_IMPL(seq_and_carry) \
+ BOOST_PP_CAT( \
+ BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ_IMPL_ \
+ , BOOST_PP_TUPLE_ELEM(2, 1, seq_and_carry) \
+ )(BOOST_PP_TUPLE_ELEM(2, 0, seq_and_carry))
+/**/
+
+#include <boost/preprocessor/seq/seq.hpp>
+#include <boost/preprocessor/seq/fold_left.hpp>
+
+// This macro treats the specified sequence of 1s and 0s like a binary number
+// in reverse and expands to a sequence representing the next value up.
+// However, if the input sequence contains all 1s, then the output sequence
+// will contain one more element but all 0s.
+//
+// Examples:
+// seq = (1)(0)(1)(0) --> return (0)(1)(1)(0)
+// seq = (1)(1)(1)(0) --> return (0)(0)(0)(1)
+// seq = (1)(1)(1)(1) --> return (0)(0)(0)(0)(0)
+#define BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ(seq) \
+ BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ_IMPL( \
+ BOOST_PP_SEQ_FOLD_LEFT( \
+ BOOST_PARAMETER_AUX_PP_INC_BINARY_SEQ_OP \
+ , (BOOST_PP_SEQ_NIL, 1) \
+ , seq \
+ ) \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/is_binary.hpp b/boost/parameter/aux_/preprocessor/is_binary.hpp
new file mode 100644
index 0000000000..a8f3c67afb
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/is_binary.hpp
@@ -0,0 +1,31 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IS_BINARY_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IS_BINARY_HPP
+
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+// From Paul Mensonides
+#include <boost/preprocessor/punctuation/comma.hpp>
+#include <boost/preprocessor/detail/split.hpp>
+#define BOOST_PARAMETER_IS_BINARY(x) \
+ BOOST_PP_SPLIT(1, BOOST_PARAMETER_IS_BINARY_C x BOOST_PP_COMMA() 0)
+/**/
+#include <boost/preprocessor/punctuation/paren.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+#define BOOST_PARAMETER_IS_BINARY_C(x,y) \
+ ~, 1 BOOST_PP_RPAREN() \
+ BOOST_PP_TUPLE_EAT(2) BOOST_PP_LPAREN() ~
+/**/
+#else
+#include <boost/preprocessor/detail/is_binary.hpp>
+#define BOOST_PARAMETER_IS_BINARY(x) BOOST_PP_IS_BINARY(x)
+#endif
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/is_nullary.hpp b/boost/parameter/aux_/preprocessor/is_nullary.hpp
new file mode 100644
index 0000000000..5d8e59c538
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/is_nullary.hpp
@@ -0,0 +1,32 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IS_NULLARY_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_IS_NULLARY_HPP
+
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+// From Paul Mensonides
+#include <boost/preprocessor/punctuation/comma.hpp>
+#include <boost/preprocessor/detail/split.hpp>
+#define BOOST_PARAMETER_IS_NULLARY(x) \
+ BOOST_PP_SPLIT(1, BOOST_PARAMETER_IS_NULLARY_C x BOOST_PP_COMMA() 0)
+/**/
+#include <boost/preprocessor/punctuation/paren.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+#define BOOST_PARAMETER_IS_NULLARY_C() \
+ ~, 1 BOOST_PP_RPAREN() \
+ BOOST_PP_TUPLE_EAT(2) BOOST_PP_LPAREN() ~
+/**/
+#else
+#include <boost/preprocessor/detail/is_nullary.hpp>
+#define BOOST_PARAMETER_IS_NULLARY(x) BOOST_PP_IS_NULLARY(x)
+/**/
+#endif
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/no_perfect_forwarding_begin.hpp b/boost/parameter/aux_/preprocessor/no_perfect_forwarding_begin.hpp
new file mode 100644
index 0000000000..9ade7adcd1
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/no_perfect_forwarding_begin.hpp
@@ -0,0 +1,165 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Copyright Cromwell D. Enage 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// No include guard. This file is intended for multiple inclusion.
+
+#define BOOST_PARAMETER_right_angle(z, n, _) >
+/**/
+
+#define BOOST_PARAMETER_satisfies_end(z, n, false_t) ,false_t>
+/**/
+
+#include <boost/preprocessor/seq/elem.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+// Generates:
+//
+// make<
+// parameter_spec##0, argument_type##0
+// , make<
+// parameter_spec##1, argument_type##1
+// , ... boost::mpl::identity<boost::parameter::aux::empty_arg_list>
+// ...>
+// >
+#define BOOST_PARAMETER_make_arg_list(z, n, names) \
+ BOOST_PP_SEQ_ELEM(0, names)< \
+ BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1, names), n), \
+ BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(2, names), n),
+/**/
+
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+
+#define BOOST_PARAMETER_build_arg_list(n, make, param_spec, arg_type) \
+ BOOST_PP_REPEAT( \
+ n, BOOST_PARAMETER_make_arg_list, (make)(param_spec)(arg_type) \
+ ) \
+ ::boost::mpl::identity< ::boost::parameter::void_> \
+ BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _)
+/**/
+
+#define BOOST_PARAMETER_make_deduced_list(z, n, names) \
+ BOOST_PP_SEQ_ELEM(0, names)<BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1, names), n),
+/**/
+
+#define BOOST_PARAMETER_build_deduced_list(n, make, parameter_spec) \
+ BOOST_PP_REPEAT( \
+ n, BOOST_PARAMETER_make_deduced_list, (make)(parameter_spec) \
+ ) \
+ ::boost::mpl::identity< ::boost::parameter::void_> \
+ BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _)
+/**/
+
+#define BOOST_PARAMETER_forward_typedef(z, n, names) \
+ typedef BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, names), n) \
+ BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1, names), n);
+/**/
+
+#define BOOST_PARAMETER_template_args(z, n, prefix) \
+ typename BOOST_PP_CAT(prefix, n) = ::boost::parameter::void_
+/**/
+
+#include <boost/mpl/pair.hpp>
+
+#if (0 < BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY)
+
+#include <boost/parameter/aux_/pack/item.hpp>
+#include <boost/preprocessor/control/iif.hpp>
+
+#define BOOST_PARAMETER_make_arg_items_R(r, prefix, i, elem) \
+ ::boost::parameter::aux::item<BOOST_PP_CAT(prefix, i), \
+ BOOST_PP_CAT(A, i) BOOST_PP_IIF(elem, &, const&),
+/**/
+
+#include <boost/parameter/aux_/pack/make_arg_list.hpp>
+#include <boost/parameter/aux_/pack/tag_keyword_arg.hpp>
+#include <boost/preprocessor/seq/for_each_i.hpp>
+#include <boost/preprocessor/seq/size.hpp>
+
+#define BOOST_PARAMETER_function_call_arg_list_R(r, seq) \
+ ::boost::parameter::aux::make_arg_list< \
+ BOOST_PP_SEQ_FOR_EACH_I_R( \
+ r, BOOST_PARAMETER_make_arg_items_R, PS, seq \
+ ) \
+ ::boost::parameter::void_ \
+ BOOST_PP_REPEAT( \
+ BOOST_PP_SEQ_SIZE(seq), BOOST_PARAMETER_right_angle, _ \
+ ) \
+ , deduced_list \
+ , ::boost::parameter::aux::tag_keyword_arg \
+ >
+/**/
+
+#include <boost/preprocessor/arithmetic/sub.hpp>
+
+#define BOOST_PARAMETER_function_call_arg_pack_init(z, n, limit) \
+ BOOST_PP_CAT(a, BOOST_PP_SUB(limit, n))
+/**/
+
+#include <boost/parameter/aux_/preprocessor/binary_seq_to_args.hpp>
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/facilities/intercept.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/enum_trailing_params.hpp>
+#include <boost/preprocessor/seq/seq.hpp>
+
+#define BOOST_PARAMETER_function_call_op_overload_R(r, seq) \
+ template < \
+ BOOST_PP_ENUM_PARAMS( \
+ BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq)) \
+ , typename A \
+ ) \
+ > \
+ inline typename ::boost::mpl::first< \
+ typename BOOST_PARAMETER_function_call_arg_list_R( \
+ r, BOOST_PP_SEQ_TAIL(seq) \
+ )::type \
+ >::type \
+ operator()( \
+ BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARGS( \
+ BOOST_PP_SEQ_TAIL(seq), (A)(a) \
+ ) \
+ ) const \
+ { \
+ typedef typename BOOST_PARAMETER_function_call_arg_list_R( \
+ r, BOOST_PP_SEQ_TAIL(seq) \
+ )::type result; \
+ typedef typename ::boost::mpl::first<result>::type result_type; \
+ typedef typename ::boost::mpl::second<result>::type error; \
+ error(); \
+ return result_type( \
+ BOOST_PP_ENUM( \
+ BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq)) \
+ , BOOST_PARAMETER_function_call_arg_pack_init \
+ , BOOST_PP_DEC(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq))) \
+ ) \
+ BOOST_PP_ENUM_TRAILING_PARAMS( \
+ BOOST_PP_SUB( \
+ BOOST_PARAMETER_COMPOSE_MAX_ARITY \
+ , BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq)) \
+ ) \
+ , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT \
+ ) \
+ ); \
+ }
+/**/
+
+#endif // exponential overloads
+
+#include <boost/parameter/aux_/pack/satisfies.hpp>
+#include <boost/mpl/eval_if.hpp>
+
+#define BOOST_PARAMETER_satisfies_begin(z, n, prefix) \
+ ::boost::mpl::eval_if< \
+ ::boost::parameter::aux::satisfies_requirements_of< \
+ typename ::boost::mpl::first<ArgumentPackAndError>::type \
+ , BOOST_PP_CAT(prefix, n) \
+ >,
+/**/
+
diff --git a/boost/parameter/aux_/preprocessor/no_perfect_forwarding_end.hpp b/boost/parameter/aux_/preprocessor/no_perfect_forwarding_end.hpp
new file mode 100644
index 0000000000..71cc596d2c
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/no_perfect_forwarding_end.hpp
@@ -0,0 +1,24 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Copyright Cromwell D. Enage 2017.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// No include guard. This file is intended for multiple inclusion.
+
+#undef BOOST_PARAMETER_satisfies_begin
+#if (0 < BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY)
+#undef BOOST_PARAMETER_function_call_op_overload_R
+#undef BOOST_PARAMETER_function_call_arg_pack_init
+#undef BOOST_PARAMETER_function_call_arg_list_R
+#undef BOOST_PARAMETER_make_arg_items_R
+#endif
+#undef BOOST_PARAMETER_template_args
+#undef BOOST_PARAMETER_forward_typedef
+#undef BOOST_PARAMETER_build_deduced_list
+#undef BOOST_PARAMETER_make_deduced_list
+#undef BOOST_PARAMETER_build_arg_list
+#undef BOOST_PARAMETER_make_arg_list
+#undef BOOST_PARAMETER_satisfies_end
+#undef BOOST_PARAMETER_right_angle
+
diff --git a/boost/parameter/aux_/preprocessor/nullptr.hpp b/boost/parameter/aux_/preprocessor/nullptr.hpp
new file mode 100644
index 0000000000..85ab6cc2da
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/nullptr.hpp
@@ -0,0 +1,18 @@
+// Copyright Cromwell D. Enage 2019.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_NULLPTR_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_NULLPTR_HPP
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_NO_CXX11_NULLPTR)
+#define BOOST_PARAMETER_AUX_PP_NULLPTR 0
+#else
+#define BOOST_PARAMETER_AUX_PP_NULLPTR nullptr
+#endif
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/overloads.hpp b/boost/parameter/aux_/preprocessor/overloads.hpp
new file mode 100644
index 0000000000..4f2685616d
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/overloads.hpp
@@ -0,0 +1,92 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// This file generates overloads in this format:
+//
+// template <typename A0, typename A1>
+// typename ::boost::mpl::apply_wrap1<
+// ::boost::parameter::aux::make_arg_list<
+// PS0,A0
+// , ::boost::parameter::aux::make_arg_list<
+// PS1,A1
+// , ::boost::mpl::identity<
+// ::boost::parameter::aux::empty_arg_list
+// >
+// >
+// >
+// , unnamed_list
+// >::type
+// operator()(A0 const& a0, A1 const& a1) const
+// {
+// typedef typename ::boost::mpl::apply_wrap1<
+// ::boost::parameter::aux::make_arg_list<
+// PS0,A0
+// , ::boost::parameter::aux::make_arg_list<
+// PS1,A1
+// , ::boost::mpl::identity<
+// ::boost::parameter::aux::empty_arg_list
+// >
+// >
+// >
+// >::type arg_tuple;
+//
+// return arg_tuple(
+// a0
+// , a1
+// , ::boost::parameter::aux::void_()
+// ...
+// );
+// }
+//
+
+#if !defined(BOOST_PP_IS_ITERATING)
+# error Boost.Parameters - do not include this file!
+#endif
+
+#define N BOOST_PP_ITERATION()
+
+#define BOOST_PARAMETER_open_list(z, n, text) \
+ ::boost::parameter::aux::item< \
+ BOOST_PP_CAT(PS, n), BOOST_PP_CAT(A, n)
+
+#define BOOST_PARAMETER_close_list(z, n, text) >
+
+#define BOOST_PARAMETER_arg_list(n) \
+ ::boost::parameter::aux::make_arg_list< \
+ BOOST_PP_ENUM(N, BOOST_PARAMETER_open_list, _) \
+ , ::boost::parameter::void_ \
+ BOOST_PP_REPEAT(N, BOOST_PARAMETER_close_list, _) \
+ , deduced_list \
+ , ::boost::parameter::aux::tag_keyword_arg \
+ >
+
+#define BOOST_PARAMETER_arg_pack_init(z, n, limit) \
+ BOOST_PP_CAT(a, BOOST_PP_SUB(limit, n))
+
+template <BOOST_PP_ENUM_PARAMS(N, typename A)>
+typename ::boost::mpl::first<
+ typename BOOST_PARAMETER_arg_list(N)::type
+>::type
+ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N, A, & a)) const
+{
+ typedef typename BOOST_PARAMETER_arg_list(N)::type result;
+ typedef typename ::boost::mpl::first<result>::type result_type;
+ typedef typename ::boost::mpl::second<result>::type error;
+ error();
+
+ return result_type(
+ BOOST_PP_ENUM(N, BOOST_PARAMETER_arg_pack_init, BOOST_PP_DEC(N))
+ BOOST_PP_ENUM_TRAILING_PARAMS(
+ BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, N)
+ , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT
+ )
+ );
+}
+
+#undef BOOST_PARAMETER_arg_list
+#undef BOOST_PARAMETER_close_list
+#undef BOOST_PARAMETER_open_list
+#undef N
+
diff --git a/boost/parameter/aux_/preprocessor/qualifier.hpp b/boost/parameter/aux_/preprocessor/qualifier.hpp
new file mode 100644
index 0000000000..b809503b44
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/qualifier.hpp
@@ -0,0 +1,88 @@
+// Copyright Daniel Wallin 2006.
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PREPROCESSOR_QUALIFIER_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_QUALIFIER_HPP
+
+#define BOOST_PARAMETER_QUALIFIER_EAT_in(x)
+#define BOOST_PARAMETER_QUALIFIER_EAT_out(x)
+#define BOOST_PARAMETER_QUALIFIER_EAT_in_out(x)
+#define BOOST_PARAMETER_QUALIFIER_EAT_consume(x)
+#define BOOST_PARAMETER_QUALIFIER_EAT_move_from(x)
+#define BOOST_PARAMETER_QUALIFIER_EAT_forward(x)
+
+#define BOOST_PARAMETER_GET_QUALIFIER_in(x) in_reference
+#define BOOST_PARAMETER_GET_QUALIFIER_out(x) out_reference
+#define BOOST_PARAMETER_GET_QUALIFIER_in_out(x) in_out_reference
+#define BOOST_PARAMETER_GET_QUALIFIER_consume(x) consume_reference
+#define BOOST_PARAMETER_GET_QUALIFIER_move_from(x) move_from_reference
+#define BOOST_PARAMETER_GET_QUALIFIER_forward(x) forward_reference
+
+#define BOOST_PARAMETER_STRIP_QUALIFIER_in(x) x
+#define BOOST_PARAMETER_STRIP_QUALIFIER_out(x) x
+#define BOOST_PARAMETER_STRIP_QUALIFIER_in_out(x) x
+#define BOOST_PARAMETER_STRIP_QUALIFIER_consume(x) x
+#define BOOST_PARAMETER_STRIP_QUALIFIER_move_from(x) x
+#define BOOST_PARAMETER_STRIP_QUALIFIER_forward(x) x
+
+#include <boost/preprocessor/cat.hpp>
+
+#define BOOST_PARAMETER_GET_QUALIFIER_GET(x) \
+ BOOST_PP_CAT(BOOST_PARAMETER_GET_QUALIFIER_, x)
+/**/
+
+#define BOOST_PARAMETER_GET_UNQUALIFIED(x) \
+ BOOST_PP_CAT(BOOST_PARAMETER_STRIP_QUALIFIER_, x)
+/**/
+
+#include <boost/preprocessor/facilities/is_empty.hpp>
+
+// Expands to 1 if x is either "in(k)", "out(k)", "in_out(k)", "consume(k)",
+// "move_from(k)", or "forward(k)"; expands to 0 otherwise.
+#define BOOST_PARAMETER_IS_QUALIFIER(x) \
+ BOOST_PP_IS_EMPTY(BOOST_PP_CAT(BOOST_PARAMETER_QUALIFIER_EAT_, x))
+/**/
+
+#include <boost/preprocessor/control/iif.hpp>
+
+// Expands to the qualifier of x,
+// where x is either a keyword qualifier or a keyword.
+//
+// k => forward_reference
+// in(k) => in_reference
+// out(k) => out_reference
+// in_out(k) => in_out_reference
+// forward(k) => forward_reference
+// consume(k) => consume_reference
+// move_from(k) => move_from_reference
+#define BOOST_PARAMETER_GET_QUALIFIER(x) \
+ BOOST_PP_IIF( \
+ BOOST_PARAMETER_IS_QUALIFIER(x) \
+ , BOOST_PARAMETER_GET_QUALIFIER_GET(x) \
+ , forward_reference \
+ )
+/**/
+
+// Expands to the unqualified version of x,
+// where x is either a keyword qualifier or a keyword.
+//
+// k => k
+// in(k) => k
+// out(k) => k
+// in_out(k) => k
+// forward(k) => k
+// consume(k) => k
+// move_from(k) => k
+#define BOOST_PARAMETER_UNQUALIFIED(x) \
+ BOOST_PP_IIF( \
+ BOOST_PARAMETER_IS_QUALIFIER(x) \
+ , BOOST_PARAMETER_GET_UNQUALIFIED(x) \
+ , x \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/seq_enum.hpp b/boost/parameter/aux_/preprocessor/seq_enum.hpp
new file mode 100644
index 0000000000..1455105d05
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/seq_enum.hpp
@@ -0,0 +1,26 @@
+// Copyright David Abrahams 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_SEQ_ENUM_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_SEQ_ENUM_HPP
+
+#include <boost/preprocessor/seq/enum.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+#if BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
+#include <boost/preprocessor/seq/size.hpp>
+// Temporary version of BOOST_PP_SEQ_ENUM
+// until Paul M. integrates the workaround.
+#define BOOST_PARAMETER_SEQ_ENUM_I(size, seq) \
+ BOOST_PP_CAT(BOOST_PP_SEQ_ENUM_, size) seq
+#define BOOST_PARAMETER_SEQ_ENUM(seq) \
+ BOOST_PARAMETER_SEQ_ENUM_I(BOOST_PP_SEQ_SIZE(seq), seq)
+#else
+#define BOOST_PARAMETER_SEQ_ENUM(seq) BOOST_PP_SEQ_ENUM(seq)
+#endif
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/preprocessor/seq_merge.hpp b/boost/parameter/aux_/preprocessor/seq_merge.hpp
new file mode 100644
index 0000000000..065375388e
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/seq_merge.hpp
@@ -0,0 +1,1807 @@
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_PREPROCESSOR_SEQ_MERGE_HPP
+#define BOOST_PARAMETER_AUX_PREPROCESSOR_SEQ_MERGE_HPP
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_0(seq0, seq1) seq1
+/**/
+
+#include <boost/preprocessor/seq/seq.hpp>
+#include <boost/preprocessor/seq/push_front.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_1(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT(seq1, BOOST_PP_SEQ_HEAD(seq0))
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_2(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_1(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_3(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_2(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_4(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_3(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_5(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_4(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_6(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_5(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_7(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_6(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_8(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_7(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_9(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_8(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_10(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_9(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_11(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_10(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_12(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_11(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_13(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_12(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_14(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_13(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_15(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_14(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_16(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_15(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_17(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_16(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_18(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_17(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_19(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_18(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_20(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_19(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_21(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_20(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_22(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_21(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_23(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_22(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_24(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_23(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_25(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_24(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_26(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_25(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_27(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_26(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_28(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_27(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_29(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_28(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_30(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_29(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_31(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_30(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_32(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_31(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_33(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_32(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_34(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_33(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_35(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_34(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_36(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_35(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_37(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_36(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_38(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_37(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_39(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_38(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_40(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_39(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_41(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_40(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_42(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_41(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_43(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_42(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_44(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_43(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_45(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_44(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_46(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_45(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_47(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_46(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_48(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_47(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_49(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_48(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_50(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_49(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_51(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_50(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_52(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_51(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_53(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_52(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_54(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_53(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_55(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_54(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_56(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_55(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_57(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_56(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_58(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_57(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_59(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_58(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_60(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_59(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_61(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_60(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_62(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_61(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_63(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_62(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_64(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_63(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_65(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_64(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_66(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_65(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_67(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_66(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_68(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_67(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_69(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_68(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_70(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_69(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_71(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_70(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_72(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_71(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_73(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_72(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_74(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_73(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_75(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_74(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_76(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_75(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_77(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_76(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_78(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_77(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_79(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_78(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_80(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_79(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_81(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_80(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_82(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_81(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_83(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_82(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_84(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_83(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_85(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_84(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_86(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_85(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_87(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_86(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_88(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_87(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_89(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_88(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_90(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_89(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_91(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_90(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_92(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_91(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_93(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_92(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_94(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_93(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_95(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_94(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_96(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_95(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_97(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_96(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_98(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_97(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_99(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_98(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_100(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_99(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_101(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_100(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_102(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_101(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_103(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_102(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_104(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_103(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_105(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_104(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_106(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_105(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_107(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_106(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_108(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_107(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_109(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_108(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_110(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_109(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_111(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_110(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_112(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_111(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_113(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_112(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_114(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_113(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_115(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_114(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_116(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_115(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_117(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_116(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_118(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_117(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_119(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_118(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_120(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_119(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_121(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_120(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_122(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_121(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_123(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_122(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_124(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_123(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_125(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_124(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_126(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_125(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_127(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_126(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_128(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_127(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_129(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_128(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_130(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_129(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_131(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_130(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_132(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_131(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_133(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_132(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_134(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_133(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_135(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_134(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_136(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_135(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_137(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_136(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_138(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_137(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_139(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_138(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_140(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_139(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_141(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_140(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_142(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_141(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_143(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_142(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_144(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_143(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_145(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_144(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_146(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_145(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_147(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_146(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_148(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_147(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_149(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_148(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_150(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_149(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_151(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_150(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_152(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_151(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_153(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_152(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_154(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_153(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_155(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_154(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_156(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_155(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_157(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_156(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_158(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_157(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_159(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_158(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_160(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_159(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_161(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_160(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_162(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_161(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_163(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_162(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_164(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_163(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_165(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_164(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_166(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_165(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_167(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_166(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_168(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_167(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_169(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_168(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_170(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_169(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_171(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_170(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_172(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_171(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_173(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_172(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_174(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_173(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_175(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_174(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_176(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_175(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_177(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_176(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_178(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_177(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_179(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_178(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_180(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_179(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_181(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_180(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_182(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_181(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_183(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_182(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_184(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_183(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_185(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_184(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_186(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_185(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_187(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_186(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_188(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_187(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_189(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_188(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_190(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_189(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_191(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_190(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_192(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_191(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_193(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_192(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_194(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_193(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_195(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_194(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_196(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_195(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_197(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_196(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_198(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_197(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_199(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_198(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_200(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_199(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_201(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_200(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_202(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_201(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_203(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_202(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_204(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_203(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_205(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_204(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_206(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_205(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_207(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_206(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_208(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_207(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_209(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_208(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_210(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_209(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_211(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_210(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_212(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_211(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_213(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_212(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_214(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_213(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_215(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_214(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_216(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_215(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_217(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_216(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_218(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_217(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_219(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_218(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_220(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_219(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_221(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_220(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_222(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_221(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_223(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_222(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_224(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_223(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_225(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_224(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_226(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_225(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_227(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_226(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_228(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_227(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_229(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_228(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_230(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_229(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_231(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_230(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_232(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_231(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_233(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_232(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_234(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_233(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_235(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_234(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_236(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_235(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_237(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_236(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_238(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_237(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_239(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_238(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_240(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_239(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_241(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_240(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_242(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_241(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_243(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_242(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_244(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_243(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_245(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_244(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_246(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_245(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_247(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_246(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_248(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_247(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_249(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_248(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_250(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_249(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_251(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_250(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_252(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_251(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_253(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_252(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_254(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_253(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE_255(seq0, seq1) \
+ BOOST_PP_SEQ_PUSH_FRONT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_254(BOOST_PP_SEQ_TAIL(seq0), seq1) \
+ , BOOST_PP_SEQ_HEAD(seq0) \
+ )
+/**/
+
+#include <boost/preprocessor/seq/size.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+#define BOOST_PARAMETER_AUX_PP_SEQ_MERGE(seq0, seq1) \
+ BOOST_PP_CAT( \
+ BOOST_PARAMETER_AUX_PP_SEQ_MERGE_, BOOST_PP_SEQ_SIZE(seq0) \
+ )(seq0, seq1)
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/result_of0.hpp b/boost/parameter/aux_/result_of0.hpp
index e0096148b4..f8cbea3c3a 100644
--- a/boost/parameter/aux_/result_of0.hpp
+++ b/boost/parameter/aux_/result_of0.hpp
@@ -1,36 +1,53 @@
-// Copyright David Abrahams 2005. Distributed under the Boost
-// Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_PARAMETER_AUX_RESULT_OF0_DWA2005511_HPP
-# define BOOST_PARAMETER_AUX_RESULT_OF0_DWA2005511_HPP
-
-# include <boost/utility/result_of.hpp>
-
-// A metafunction returning the result of invoking a nullary function
-// object of the given type.
+// Copyright David Abrahams 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_NO_RESULT_OF
-
-# include <boost/utility/result_of.hpp>
-namespace boost { namespace parameter { namespace aux {
-template <class F>
-struct result_of0 : result_of<F()>
-{};
+#ifndef BOOST_PARAMETER_AUX_RESULT_OF0_DWA2005511_HPP
+#define BOOST_PARAMETER_AUX_RESULT_OF0_DWA2005511_HPP
-}}} // namespace boost::parameter::aux_
+#include <boost/parameter/aux_/use_default_tag.hpp>
+#include <boost/parameter/config.hpp>
+#include <boost/utility/result_of.hpp>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
#else
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_void.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ // A metafunction returning the result of invoking
+ // a nullary function object of the given type.
+ template <typename F>
+ class result_of0
+ {
+#if defined(BOOST_NO_RESULT_OF)
+ typedef typename F::result_type result_of_F;
+#else
+ typedef typename ::boost::result_of<F()>::type result_of_F;
+#endif
-namespace boost { namespace parameter { namespace aux {
-template <class F>
-struct result_of0
-{
- typedef typename F::result_type type;
-};
-
-}}} // namespace boost::parameter::aux_
-
-#endif
+ public:
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_if<
+ ::std::is_void<result_of_F>
+#else
+ typedef typename ::boost::mpl::if_<
+ ::boost::is_void<result_of_F>
+#endif
+ , ::boost::parameter::aux::use_default_tag
+ , result_of_F
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >;
+#else
+ >::type type;
+#endif
+ };
+}}} // namespace boost::parameter::aux
+#endif // include guard
-#endif // BOOST_PARAMETER_AUX_RESULT_OF0_DWA2005511_HPP
diff --git a/boost/parameter/aux_/set.hpp b/boost/parameter/aux_/set.hpp
index 7ab93dc7bb..418b0b174d 100644
--- a/boost/parameter/aux_/set.hpp
+++ b/boost/parameter/aux_/set.hpp
@@ -1,66 +1,118 @@
-// Copyright Daniel Wallin 2006. Use, modification and distribution is
-// subject to the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARAMETER_SET_060912_HPP
-# define BOOST_PARAMETER_SET_060912_HPP
+#define BOOST_PARAMETER_SET_060912_HPP
-# include <boost/detail/workaround.hpp>
+#include <boost/parameter/config.hpp>
-# if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-# include <boost/mpl/insert.hpp>
-# include <boost/mpl/set/set0.hpp>
-# include <boost/mpl/has_key.hpp>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/list.hpp>
namespace boost { namespace parameter { namespace aux {
-typedef mpl::set0<> set0;
+ typedef ::boost::mp11::mp_list<> set0;
+}}} // namespace boost::parameter::aux
+
+#include <boost/mp11/algorithm.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename S, typename K>
+ struct insert_
+ {
+ using type = ::boost::mp11::mp_insert_c<S,0,K>;
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Set, typename K>
+ struct has_key_
+ {
+ using type = ::boost::mp11::mp_if<
+ ::boost::mp11::mp_empty<Set>
+ , ::boost::mp11::mp_false
+ , ::std::is_same<
+ ::boost::mp11::mp_find<Set,K>
+ , ::boost::mp11::mp_size<Set>
+ >
+ >;
+ };
+}}} // namespace boost::parameter::aux
+
+#elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+#include <boost/mpl/list.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ typedef ::boost::mpl::list0<> set0;
+}}} // namespace boost::parameter::aux
-template <class Set, class K>
-struct insert_
-{
- typedef typename mpl::insert<Set, K>::type type;
-};
+#include <boost/mpl/push_front.hpp>
-template <class Set, class K>
-struct has_key_
-{
- typedef typename mpl::has_key<Set, K>::type type;
-};
+namespace boost { namespace parameter { namespace aux {
+ template <typename Set, typename K>
+ struct insert_ : ::boost::mpl::push_front<Set,K>
+ {
+ };
}}} // namespace boost::parameter::aux
-# else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/end.hpp>
+#include <boost/mpl/find.hpp>
+#include <boost/type_traits/is_same.hpp>
-# include <boost/mpl/list.hpp>
-# include <boost/mpl/end.hpp>
-# include <boost/mpl/find.hpp>
-# include <boost/mpl/not.hpp>
-# include <boost/mpl/push_front.hpp>
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Set, typename K>
+ struct has_key_
+ {
+ typedef typename ::boost::mpl::find<Set,K>::type iter;
+ typedef typename ::boost::mpl::if_<
+ ::boost::is_same<iter,typename ::boost::mpl::end<Set>::type>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >::type type;
+ };
+}}} // namespace boost::parameter::aux
+
+#else // !BOOST_PARAMETER_CAN_USE_MP11 && Borland workarounds not needed
+#include <boost/mpl/set/set0.hpp>
namespace boost { namespace parameter { namespace aux {
-typedef mpl::list0<> set0;
+ typedef ::boost::mpl::set0<> set0;
+}}} // namespace boost::parameter::aux
-template <class Set, class K>
-struct insert_
-{
- typedef typename mpl::push_front<Set, K>::type type;
-};
+#include <boost/mpl/insert.hpp>
-template <class Set, class K>
-struct has_key_
-{
- typedef typename mpl::find<Set, K>::type iter;
- typedef mpl::not_<
- is_same<iter, typename mpl::end<Set>::type>
- > type;
-};
+namespace boost { namespace parameter { namespace aux {
+ template <typename Set, typename K>
+ struct insert_ : ::boost::mpl::insert<Set,K>
+ {
+ };
}}} // namespace boost::parameter::aux
-# endif
+#include <boost/mpl/has_key.hpp>
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Set, typename K>
+ struct has_key_ : ::boost::mpl::has_key<Set,K>
+ {
+ };
+}}} // namespace boost::parameter::aux
-#endif // BOOST_PARAMETER_SET_060912_HPP
+#endif // BOOST_PARAMETER_CAN_USE_MP11 || Borland workarounds needed
+#endif // include guard
diff --git a/boost/parameter/aux_/tag.hpp b/boost/parameter/aux_/tag.hpp
index 475efb9e4a..0cba191d6a 100644
--- a/boost/parameter/aux_/tag.hpp
+++ b/boost/parameter/aux_/tag.hpp
@@ -1,38 +1,160 @@
-// Copyright David Abrahams 2005. Distributed under the 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 David Abrahams 2005.
+// Copyright Cromwell D. Enage 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_PARAMETER_AUX_TAG_DWA2005610_HPP
-# define BOOST_PARAMETER_AUX_TAG_DWA2005610_HPP
+#define BOOST_PARAMETER_AUX_TAG_DWA2005610_HPP
+
+#include <boost/parameter/aux_/unwrap_cv_reference.hpp>
+#include <boost/parameter/aux_/tagged_argument.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11) && \
+ !BOOST_WORKAROUND(BOOST_MSVC, >= 1910)
+// MSVC-14.1+ assigns rvalue references to tagged_argument instances
+// instead of tagged_argument_rref instances with this code.
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Keyword, typename Arg>
+ struct tag_if_lvalue_reference
+ {
+ using type = ::boost::parameter::aux::tagged_argument_list_of_1<
+ ::boost::parameter::aux::tagged_argument<
+ Keyword
+ , typename ::boost::parameter::aux
+ ::unwrap_cv_reference<Arg>::type
+ >
+ >;
+ };
+
+ template <typename Keyword, typename Arg>
+ struct tag_if_scalar
+ {
+ using type = ::boost::parameter::aux::tagged_argument_list_of_1<
+ ::boost::parameter::aux
+ ::tagged_argument<Keyword,typename ::std::add_const<Arg>::type>
+ >;
+ };
+
+ template <typename Keyword, typename Arg>
+ using tag_if_otherwise = ::boost::mp11::mp_if<
+ ::std::is_scalar<typename ::std::remove_const<Arg>::type>
+ , ::boost::parameter::aux::tag_if_scalar<Keyword,Arg>
+ , ::boost::mp11::mp_identity<
+ ::boost::parameter::aux::tagged_argument_list_of_1<
+ ::boost::parameter::aux::tagged_argument_rref<Keyword,Arg>
+ >
+ >
+ >;
+
+ template <typename Keyword, typename Arg>
+ using tag = ::boost::mp11::mp_if<
+ ::boost::mp11::mp_if<
+ ::std::is_lvalue_reference<Arg>
+ , ::boost::mp11::mp_true
+ , ::boost::parameter::aux::is_cv_reference_wrapper<Arg>
+ >
+ , ::boost::parameter::aux::tag_if_lvalue_reference<Keyword,Arg>
+ , ::boost::parameter::aux::tag_if_otherwise<Keyword,Arg>
+ >;
+}}} // namespace boost::parameter::aux_
-# include <boost/parameter/aux_/unwrap_cv_reference.hpp>
-# include <boost/parameter/aux_/tagged_argument.hpp>
+#elif defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/is_scalar.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
+#include <boost/type_traits/remove_const.hpp>
namespace boost { namespace parameter { namespace aux {
-template <class Keyword, class ActualArg
+ template <typename Keyword, typename ActualArg>
+ struct tag
+ {
+ typedef typename ::boost::parameter::aux
+ ::unwrap_cv_reference<ActualArg>::type Arg;
+ typedef typename ::boost::add_const<Arg>::type ConstArg;
+ typedef typename ::boost::remove_const<Arg>::type MutArg;
+ typedef typename ::boost::mpl::eval_if<
+ typename ::boost::mpl::if_<
+ ::boost::is_lvalue_reference<ActualArg>
+ , ::boost::mpl::true_
+ , ::boost::parameter::aux::is_cv_reference_wrapper<ActualArg>
+ >::type
+ , ::boost::mpl::identity<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::parameter::aux::tagged_argument_list_of_1<
+#endif
+ ::boost::parameter::aux::tagged_argument<Keyword,Arg>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >
+#endif
+ >
+ , ::boost::mpl::if_<
+ ::boost::is_scalar<MutArg>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ , ::boost::parameter::aux::tagged_argument_list_of_1<
+ ::boost::parameter::aux::tagged_argument<Keyword,ConstArg>
+ >
+ , ::boost::parameter::aux::tagged_argument_list_of_1<
+ ::boost::parameter::aux::tagged_argument_rref<Keyword,Arg>
+ >
+#else
+ , ::boost::parameter::aux::tagged_argument<Keyword,ConstArg>
+ , ::boost::parameter::aux::tagged_argument_rref<Keyword,Arg>
+#endif
+ >
+ >::type type;
+ };
+}}} // namespace boost::parameter::aux_
+
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <
+ typename Keyword
+ , typename Arg
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- , class = typename is_cv_reference_wrapper<ActualArg>::type
-#endif
- >
-struct tag
-{
- typedef tagged_argument<
- Keyword
- , typename unwrap_cv_reference<ActualArg>::type
- > type;
-};
+ , typename = typename ::boost::parameter::aux
+ ::is_cv_reference_wrapper<Arg>::type
+#endif
+ >
+ struct tag
+ {
+ typedef ::boost::parameter::aux::tagged_argument<
+ Keyword
+ , typename ::boost::parameter::aux::unwrap_cv_reference<Arg>::type
+ > type;
+ };
+}}} // namespace boost::parameter::aux_
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-template <class Keyword, class ActualArg>
-struct tag<Keyword,ActualArg,mpl::false_>
-{
- typedef tagged_argument<
- Keyword
- , ActualArg
- > type;
-};
-#endif
+#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+ template <typename Keyword, typename Arg>
+ struct tag<Keyword,Arg,::boost::mpl::false_>
+ {
+ typedef ::boost::parameter::aux::tagged_argument<
+ Keyword
+ , typename ::boost::remove_reference<Arg>::type
+ > type;
+ };
}}} // namespace boost::parameter::aux_
-#endif // BOOST_PARAMETER_AUX_TAG_DWA2005610_HPP
+#endif // Borland workarounds needed.
+#endif // MP11 or perfect forwarding support
+#endif // include guard
+
diff --git a/boost/parameter/aux_/tagged_argument.hpp b/boost/parameter/aux_/tagged_argument.hpp
index 79d273e418..964dd8fd00 100644
--- a/boost/parameter/aux_/tagged_argument.hpp
+++ b/boost/parameter/aux_/tagged_argument.hpp
@@ -1,188 +1,894 @@
-// Copyright Daniel Wallin, David Abrahams 2005. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Copyright Cromwell D. Enage 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_PARAMETER_TAGGED_ARGUMENT_050328_HPP
-# define BOOST_PARAMETER_TAGGED_ARGUMENT_050328_HPP
-
-# include <boost/parameter/aux_/void.hpp>
-# include <boost/parameter/aux_/arg_list.hpp>
-# include <boost/parameter/aux_/result_of0.hpp>
-# include <boost/mpl/if.hpp>
-# include <boost/mpl/apply_wrap.hpp>
-# include <boost/mpl/and.hpp>
-# include <boost/mpl/not.hpp>
-# include <boost/type_traits/is_same.hpp>
-# include <boost/type_traits/is_convertible.hpp>
-# include <boost/type_traits/is_reference.hpp>
+#define BOOST_PARAMETER_TAGGED_ARGUMENT_050328_HPP
namespace boost { namespace parameter { namespace aux {
-struct empty_arg_list;
-struct arg_list_tag;
+ struct error_const_lvalue_bound_to_out_parameter;
+ struct error_lvalue_bound_to_consume_parameter;
+ struct error_rvalue_bound_to_out_parameter;
+}}} // namespace boost::parameter::aux
-struct tagged_argument_base {};
+#include <boost/parameter/keyword_fwd.hpp>
+#include <boost/parameter/config.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_const.hpp>
-// Holds a reference to an argument of type Arg associated with
-// keyword Keyword
-
-template <class Keyword, class Arg>
-struct tagged_argument : tagged_argument_base
-{
- typedef Keyword key_type;
- typedef Arg value_type;
- typedef Arg& reference;
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#endif
- tagged_argument(reference x) : value(x) {}
+namespace boost { namespace parameter { namespace aux {
- // A metafunction class that, given a keyword and a default
- // type, returns the appropriate result type for a keyword
- // lookup given that default
- struct binding
+ template <typename Keyword, typename Arg>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using tagged_argument_type = ::boost::mp11::mp_if<
+ ::boost::mp11::mp_if<
+ ::std::is_scalar<Arg>
+ , ::boost::mp11::mp_false
+ , ::std::is_same<
+ typename Keyword::qualifier
+ , ::boost::parameter::consume_reference
+ >
+ >
+ , ::boost::parameter::aux::error_lvalue_bound_to_consume_parameter
+ , ::boost::mp11::mp_if<
+ ::std::is_const<Arg>
+ , ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Keyword::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::parameter::aux
+ ::error_const_lvalue_bound_to_out_parameter
+ , ::std::remove_const<Arg>
+ >
+ , ::boost::mp11::mp_identity<Arg>
+ >
+ >;
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ struct tagged_argument_type
+ : ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Keyword::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::parameter::aux::error_const_lvalue_bound_to_out_parameter
+ , ::boost::remove_const<Arg>
+ >
{
- template <class KW, class Default, class Reference>
- struct apply
- {
- typedef typename mpl::eval_if<
- boost::is_same<KW, key_type>
- , mpl::if_<Reference, reference, value_type>
- , mpl::identity<Default>
- >::type type;
- };
};
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}}} // namespace boost::parameter::aux
- // Comma operator to compose argument list without using parameters<>.
- // Useful for argument lists with undetermined length.
- template <class Keyword2, class Arg2>
- arg_list<
- tagged_argument<Keyword, Arg>
- , arg_list<tagged_argument<Keyword2, Arg2> >
- >
- operator,(tagged_argument<Keyword2, Arg2> x) const
- {
- return arg_list<
- tagged_argument<Keyword, Arg>
- , arg_list<tagged_argument<Keyword2, Arg2> >
- >(
- *this
- , arg_list<tagged_argument<Keyword2, Arg2> >(x, empty_arg_list())
- );
- }
-
- reference operator[](keyword<Keyword> const&) const
- {
- return value;
- }
+#include <boost/parameter/aux_/tagged_argument_fwd.hpp>
+#include <boost/parameter/aux_/is_tagged_argument.hpp>
+#include <boost/parameter/aux_/default.hpp>
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/parameter/aux_/arg_list.hpp>
+#include <boost/parameter/aux_/result_of0.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/is_scalar.hpp>
+#include <boost/type_traits/remove_reference.hpp>
-# if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- template <class KW, class Default>
- Default& get_with_default(default_<KW,Default> const& x, int) const
- {
- return x.value;
- }
+#if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
+#include <boost/function.hpp>
+#else
+#include <functional>
+#endif
- template <class Default>
- reference get_with_default(default_<key_type,Default> const&, long) const
- {
- return value;
- }
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#include <boost/core/enable_if.hpp>
+#include <utility>
- template <class KW, class Default>
- typename mpl::apply_wrap3<binding, KW, Default&, mpl::true_>::type
- operator[](default_<KW,Default> const& x) const
- {
- return get_with_default(x, 0L);
- }
+namespace boost { namespace parameter { namespace aux {
- template <class KW, class F>
- typename result_of0<F>::type
- get_with_lazy_default(lazy_default<KW,F> const& x, int) const
+ // Holds an lvalue reference to an argument of type Arg associated with
+ // keyword Keyword
+ template <typename Keyword, typename Arg>
+ class tagged_argument
+ : public ::boost::parameter::aux::tagged_argument_base
{
- return x.compute_default();
- }
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using arg_type = typename ::boost::parameter::aux
+ ::tagged_argument_type<Keyword,Arg>::type;
+#else
+ typedef typename ::boost::mpl::eval_if<
+ typename ::boost::mpl::eval_if<
+ ::boost::is_scalar<Arg>
+ , ::boost::mpl::false_
+ , ::boost::is_same<
+ typename Keyword::qualifier
+ , ::boost::parameter::consume_reference
+ >
+ >::type
+ , ::boost::parameter::aux::error_lvalue_bound_to_consume_parameter
+ , ::boost::mpl::eval_if<
+ ::boost::is_const<Arg>
+ , ::boost::parameter::aux::tagged_argument_type<Keyword,Arg>
+ , ::boost::mpl::identity<Arg>
+ >
+ >::type arg_type;
+#endif // BOOST_PARAMETER_CAN_USE_MP11
- template <class F>
- reference get_with_lazy_default(lazy_default<key_type,F> const&, long) const
- {
- return value;
- }
-
- template <class KW, class F>
- typename mpl::apply_wrap3<
- binding,KW
- , typename result_of0<F>::type
- , mpl::true_
- >::type
- operator[](lazy_default<KW,F> const& x) const
- {
- return get_with_lazy_default(x, 0L);
- }
-# else
- template <class Default>
- reference operator[](default_<key_type,Default> const& ) const
- {
- return value;
- }
+ public:
+ typedef Keyword key_type;
+
+ // Wrap plain (non-UDT) function objects in either
+ // a boost::function or a std::function. -- Cromwell D. Enage
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using value_type = ::boost::mp11::mp_if<
+ ::std::is_function<arg_type>
+ , ::std::function<arg_type>
+ , Arg
+ >;
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typedef typename ::boost::mpl::if_<
+ ::boost::is_function<arg_type>
+#if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
+ , ::boost::function<arg_type>
+#else
+ , ::std::function<arg_type>
+#endif
+ , Arg
+ >::type value_type;
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+ // If Arg is void_, then this type will evaluate to void_&. If the
+ // supplied argument is a plain function, then this type will evaluate
+ // to a reference-to-const function wrapper type. If the supplied
+ // argument is an lvalue, then Arg will be deduced to the lvalue
+ // reference. -- Cromwell D. Enage
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using reference = ::boost::mp11::mp_if<
+ ::std::is_function<arg_type>
+ , value_type const&
+ , Arg&
+ >;
+#else
+ typedef typename ::boost::mpl::if_<
+ ::boost::is_function<arg_type>
+ , value_type const&
+ , Arg&
+ >::type reference;
+#endif
+
+ private:
+ // Store plain functions by value, everything else by reference.
+ // -- Cromwell D. Enage
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::std::is_function<arg_type>
+ , value_type
+ , reference
+ > value;
+#else
+ typename ::boost::mpl::if_<
+ ::boost::is_function<arg_type>
+ , value_type
+ , reference
+ >::type value;
+#endif
+
+ public:
+ inline explicit BOOST_CONSTEXPR tagged_argument(reference x)
+ : value(x)
+ {
+ }
- template <class F>
- reference operator[](lazy_default<key_type,F> const& ) const
+ inline BOOST_CONSTEXPR tagged_argument(tagged_argument const& copy)
+ : value(copy.value)
+ {
+ }
+
+ // A metafunction class that, given a keyword and a default type,
+ // returns the appropriate result type for a keyword lookup given
+ // that default.
+ struct binding
+ {
+ template <typename KW, typename Default, typename Reference>
+ struct apply
+ : ::boost::mpl::eval_if<
+ ::boost::is_same<KW,key_type>
+ , ::boost::mpl::if_<Reference,reference,value_type>
+ , ::boost::mpl::identity<Default>
+ >
+ {
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename KW, typename Default, typename Reference>
+ using fn = ::boost::mp11::mp_if<
+ ::std::is_same<KW,key_type>
+ , ::boost::mp11::mp_if<Reference,reference,value_type>
+ , Default
+ >;
+#endif
+ };
+
+#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ // Comma operator to compose argument list without using parameters<>.
+ // Useful for argument lists with undetermined length.
+ template <typename Keyword2, typename Arg2>
+ inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword,Arg>
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword2,Arg2>
+ >
+ >
+ operator,(
+ ::boost::parameter::aux
+ ::tagged_argument<Keyword2,Arg2> const& x
+ ) const
+ {
+ return ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword,Arg>
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword2,Arg2>
+ >
+ >(
+ *this
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword2,Arg2>
+ >(x, ::boost::parameter::aux::empty_arg_list())
+ );
+ }
+
+ template <typename Keyword2, typename Arg2>
+ inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword,Arg>
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument_rref<Keyword2,Arg2>
+ >
+ >
+ operator,(
+ ::boost::parameter::aux
+ ::tagged_argument_rref<Keyword2,Arg2> const& x
+ ) const
+ {
+ return ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword,Arg>
+ , boost::parameter::aux::arg_list<
+ boost::parameter::aux::tagged_argument_rref<Keyword2,Arg2>
+ >
+ >(
+ *this
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux
+ ::tagged_argument_rref<Keyword2,Arg2>
+ >(x, ::boost::parameter::aux::empty_arg_list())
+ );
+ }
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+ // Accessor interface.
+ inline BOOST_CONSTEXPR reference get_value() const
+ {
+ return this->value;
+ }
+
+ inline BOOST_CONSTEXPR reference
+ operator[](::boost::parameter::keyword<Keyword> const&) const
+ {
+ return this->get_value();
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ ::boost::parameter::aux::default_<key_type,Default> const&
+ ) const
+ {
+ return this->get_value();
+ }
+
+ template <typename F>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ ::boost::parameter::aux::lazy_default<key_type,F> const&
+ ) const
+ {
+ return this->get_value();
+ }
+
+ template <typename KW, typename Default>
+ inline BOOST_CONSTEXPR Default&
+ operator[](
+ ::boost::parameter::aux::default_<KW,Default> const& x
+ ) const
+ {
+ return x.value;
+ }
+
+ template <typename KW, typename Default>
+ inline BOOST_CONSTEXPR Default&&
+ operator[](
+ ::boost::parameter::aux::default_r_<KW,Default> const& x
+ ) const
+ {
+ return ::std::forward<Default>(x.value);
+ }
+
+ template <typename KW, typename F>
+ inline BOOST_CONSTEXPR
+ typename ::boost::parameter::aux::result_of0<F>::type
+ operator[](
+ ::boost::parameter::aux::lazy_default<KW,F> const& x
+ ) const
+ {
+ return x.compute_default();
+ }
+
+ template <typename ParameterRequirements>
+ static BOOST_CONSTEXPR typename ParameterRequirements::has_default
+ satisfies(ParameterRequirements*);
+
+ template <typename HasDefault, typename Predicate>
+ static BOOST_CONSTEXPR
+ typename ::boost::mpl::apply_wrap1<Predicate,value_type>::type
+ satisfies(
+ ::boost::parameter::aux::parameter_requirements<
+ key_type
+ , Predicate
+ , HasDefault
+ >*
+ );
+
+ // MPL sequence support
+ // Convenience for users
+ typedef ::boost::parameter::aux::tagged_argument<Keyword,Arg> type;
+ // For the benefit of iterators
+ typedef ::boost::parameter::aux::empty_arg_list tail_type;
+ // For dispatching to sequence intrinsics
+ typedef ::boost::parameter::aux::arg_list_tag tag;
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename Keyword>
+ using tagged_argument_rref_key = ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Keyword::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::parameter::aux::error_rvalue_bound_to_out_parameter
+ , ::boost::mp11::mp_identity<Keyword>
+ >;
+#endif
+
+ // Holds an rvalue reference to an argument of type Arg associated with
+ // keyword Keyword
+ template <typename Keyword, typename Arg>
+ struct tagged_argument_rref
+ : ::boost::parameter::aux::tagged_argument_base
{
- return value;
- }
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using key_type = typename ::boost::parameter::aux
+ ::tagged_argument_rref_key<Keyword>::type;
+#else
+ typedef typename ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Keyword::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::parameter::aux::error_rvalue_bound_to_out_parameter
+ , ::boost::mpl::identity<Keyword>
+ >::type key_type;
+#endif
+ typedef Arg value_type;
+ typedef Arg&& reference;
+
+ private:
+ reference value;
+
+ public:
+ inline explicit BOOST_CONSTEXPR tagged_argument_rref(reference x)
+ : value(::std::forward<Arg>(x))
+ {
+ }
+
+ inline BOOST_CONSTEXPR tagged_argument_rref(
+ tagged_argument_rref const& copy
+ ) : value(::std::forward<Arg>(copy.value))
+ {
+ }
- template <class KW, class Default>
- Default& operator[](default_<KW,Default> const& x) const
+ // A metafunction class that, given a keyword and a default type,
+ // returns the appropriate result type for a keyword lookup given
+ // that default.
+ struct binding
+ {
+ template <typename KW, typename Default, typename Reference>
+ struct apply
+ {
+ typedef typename ::boost::mpl::eval_if<
+ ::boost::is_same<KW,key_type>
+ , ::boost::mpl::if_<Reference,reference,value_type>
+ , ::boost::mpl::identity<Default>
+ >::type type;
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename KW, typename Default, typename Reference>
+ using fn = ::boost::mp11::mp_if<
+ ::std::is_same<KW,key_type>
+ , ::boost::mp11::mp_if<Reference,reference,value_type>
+ , Default
+ >;
+#endif
+ };
+
+#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ // Comma operator to compose argument list without using parameters<>.
+ // Useful for argument lists with undetermined length.
+ template <typename Keyword2, typename Arg2>
+ inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument_rref<Keyword,Arg>
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword2,Arg2>
+ >
+ >
+ operator,(
+ ::boost::parameter::aux
+ ::tagged_argument<Keyword2,Arg2> const& x
+ ) const
+ {
+ return boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument_rref<Keyword,Arg>
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword2,Arg2>
+ >
+ >(
+ *this
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword2,Arg2>
+ >(x, ::boost::parameter::aux::empty_arg_list())
+ );
+ }
+
+ template <typename Keyword2, typename Arg2>
+ inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument_rref<Keyword,Arg>
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument_rref<Keyword2,Arg2>
+ >
+ >
+ operator,(
+ ::boost::parameter::aux
+ ::tagged_argument_rref<Keyword2,Arg2> const& x
+ ) const
+ {
+ return ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument_rref<Keyword,Arg>
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux
+ ::tagged_argument_rref<Keyword2,Arg2>
+ >
+ >(
+ *this
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument_rref<
+ Keyword2
+ , Arg2
+ >
+ >(x, ::boost::parameter::aux::empty_arg_list())
+ );
+ }
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+ // Accessor interface.
+ inline BOOST_CONSTEXPR reference get_value() const
+ {
+ return ::std::forward<Arg>(this->value);
+ }
+
+ inline BOOST_CONSTEXPR reference
+ operator[](::boost::parameter::keyword<Keyword> const&) const
+ {
+ return this->get_value();
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ ::boost::parameter::aux::default_<key_type,Default> const&
+ ) const
+ {
+ return this->get_value();
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ ::boost::parameter::aux::default_r_<key_type,Default> const&
+ ) const
+ {
+ return this->get_value();
+ }
+
+ template <typename F>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ ::boost::parameter::aux::lazy_default<key_type,F> const&
+ ) const
+ {
+ return this->get_value();
+ }
+
+ template <typename KW, typename Default>
+ inline BOOST_CONSTEXPR Default&
+ operator[](
+ ::boost::parameter::aux::default_<KW,Default> const& x
+ ) const
+ {
+ return x.value;
+ }
+
+ template <typename KW, typename Default>
+ inline BOOST_CONSTEXPR Default&&
+ operator[](
+ ::boost::parameter::aux::default_r_<KW,Default> const& x
+ ) const
+ {
+ return ::std::forward<Default>(x.value);
+ }
+
+ template <typename KW, typename F>
+ inline BOOST_CONSTEXPR
+ typename ::boost::parameter::aux::result_of0<F>::type
+ operator[](
+ ::boost::parameter::aux::lazy_default<KW,F> const& x
+ ) const
+ {
+ return x.compute_default();
+ }
+
+ template <typename ParameterRequirements>
+ static BOOST_CONSTEXPR typename ParameterRequirements::has_default
+ satisfies(ParameterRequirements*);
+
+ template <typename HasDefault, typename Predicate>
+ static BOOST_CONSTEXPR
+ typename ::boost::mpl::apply_wrap1<Predicate,value_type>::type
+ satisfies(
+ ::boost::parameter::aux::parameter_requirements<
+ key_type
+ , Predicate
+ , HasDefault
+ >*
+ );
+
+ // MPL sequence support
+ // Convenience for users
+ typedef ::boost::parameter::aux
+ ::tagged_argument_rref<Keyword,Arg> type;
+ // For the benefit of iterators
+ typedef ::boost::parameter::aux::empty_arg_list tail_type;
+ // For dispatching to sequence intrinsics
+ typedef ::boost::parameter::aux::arg_list_tag tag;
+ };
+}}} // namespace boost::parameter::aux
+
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+namespace boost { namespace parameter { namespace aux {
+
+ // Holds an lvalue reference to an argument of type Arg associated with
+ // keyword Keyword
+ template <typename Keyword, typename Arg>
+ class tagged_argument
+ : public ::boost::parameter::aux::tagged_argument_base
{
- return x.value;
- }
+ typedef typename ::boost::remove_const<Arg>::type arg_type;
+
+ public:
+ typedef Keyword key_type;
+
+ // Wrap plain (non-UDT) function objects in either
+ // a boost::function or a std::function. -- Cromwell D. Enage
+ typedef typename ::boost::mpl::if_<
+ ::boost::is_function<arg_type>
+#if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
+ , ::boost::function<arg_type>
+#else
+ , ::std::function<arg_type>
+#endif
+ , Arg
+ >::type value_type;
+
+ // If Arg is void_, then this type will evaluate to void_&. If the
+ // supplied argument is a plain function, then this type will evaluate
+ // to a reference-to-const function wrapper type. If the supplied
+ // argument is an lvalue, then Arg will be deduced to the lvalue
+ // reference. -- Cromwell D. Enage
+ typedef typename ::boost::mpl::if_<
+ ::boost::is_function<arg_type>
+ , value_type const&
+ , Arg&
+ >::type reference;
+
+ private:
+ // Store plain functions by value, everything else by reference.
+ // -- Cromwell D. Enage
+ typename ::boost::mpl::if_<
+ ::boost::is_function<arg_type>
+ , value_type
+ , reference
+ >::type value;
+
+ public:
+ inline explicit BOOST_CONSTEXPR tagged_argument(reference x)
+ : value(x)
+ {
+ }
+
+ inline BOOST_CONSTEXPR tagged_argument(tagged_argument const& copy)
+ : value(copy.value)
+ {
+ }
+
+ // A metafunction class that, given a keyword and a default type,
+ // returns the appropriate result type for a keyword lookup given
+ // that default.
+ struct binding
+ {
+ template <typename KW, typename Default, typename Reference>
+ struct apply
+ {
+ typedef typename ::boost::mpl::eval_if<
+ ::boost::is_same<KW,key_type>
+ , ::boost::mpl::if_<Reference,reference,value_type>
+ , ::boost::mpl::identity<Default>
+ >::type type;
+ };
+ };
+
+ // Comma operator to compose argument list without using parameters<>.
+ // Useful for argument lists with undetermined length.
+ template <typename Keyword2, typename Arg2>
+ inline ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword,Arg>
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword2,Arg2>
+ >
+ >
+ operator,(
+ ::boost::parameter::aux
+ ::tagged_argument<Keyword2,Arg2> const& x
+ ) const
+ {
+ return ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword,Arg>
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword2,Arg2>
+ >
+ >(
+ *this
+ , ::boost::parameter::aux::arg_list<
+ ::boost::parameter::aux::tagged_argument<Keyword2,Arg2>
+ >(x, ::boost::parameter::aux::empty_arg_list())
+ );
+ }
+
+ // Accessor interface.
+ inline BOOST_CONSTEXPR reference get_value() const
+ {
+ return this->value;
+ }
+
+ inline BOOST_CONSTEXPR reference
+ operator[](::boost::parameter::keyword<Keyword> const&) const
+ {
+ return this->get_value();
+ }
+
+#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || \
+ BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ template <typename KW, typename Default>
+ inline BOOST_CONSTEXPR Default&
+ get_with_default(
+ ::boost::parameter::aux::default_<KW,Default> const& x
+ , int
+ ) const
+ {
+ return x.value;
+ }
- template <class KW, class F>
- typename result_of0<F>::type operator[](lazy_default<KW,F> const& x) const
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ get_with_default(
+ ::boost::parameter::aux::default_<key_type,Default> const&
+ , long
+ ) const
+ {
+ return this->get_value();
+ }
+
+ template <typename KW, typename Default>
+ inline BOOST_CONSTEXPR typename ::boost::mpl::apply_wrap3<
+ binding
+ , KW
+ , Default&
+ , ::boost::mpl::true_
+ >::type
+ operator[](
+ ::boost::parameter::aux::default_<KW,Default> const& x
+ ) const
+ {
+ return this->get_with_default(x, 0L);
+ }
+
+ template <typename KW, typename F>
+ inline BOOST_CONSTEXPR
+ typename ::boost::parameter::aux::result_of0<F>::type
+ get_with_lazy_default(
+ ::boost::parameter::aux::lazy_default<KW,F> const& x
+ , int
+ ) const
+ {
+ return x.compute_default();
+ }
+
+ template <typename F>
+ inline BOOST_CONSTEXPR reference
+ get_with_lazy_default(
+ ::boost::parameter::aux::lazy_default<key_type,F> const&
+ , long
+ ) const
+ {
+ return this->get_value();
+ }
+
+ template <typename KW, typename F>
+ inline BOOST_CONSTEXPR typename ::boost::mpl::apply_wrap3<
+ binding
+ , KW
+ , typename ::boost::parameter::aux::result_of0<F>::type
+ , ::boost::mpl::true_
+ >::type
+ operator[](
+ ::boost::parameter::aux::lazy_default<KW,F> const& x
+ ) const
+ {
+ return this->get_with_lazy_default(x, 0L);
+ }
+#else // No function template ordering or Borland workarounds needed.
+ template <typename Default>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ ::boost::parameter::aux::default_<key_type,Default> const&
+ ) const
+ {
+ return this->get_value();
+ }
+
+ template <typename F>
+ inline BOOST_CONSTEXPR reference
+ operator[](
+ ::boost::parameter::aux::lazy_default<key_type,F> const&
+ ) const
+ {
+ return this->get_value();
+ }
+
+ template <typename KW, typename Default>
+ inline BOOST_CONSTEXPR Default&
+ operator[](
+ ::boost::parameter::aux::default_<KW,Default> const& x
+ ) const
+ {
+ return x.value;
+ }
+
+ template <typename KW, typename F>
+ inline BOOST_CONSTEXPR
+ typename ::boost::parameter::aux::result_of0<F>::type
+ operator[](
+ ::boost::parameter::aux::lazy_default<KW,F> const& x
+ ) const
+ {
+ return x.compute_default();
+ }
+
+ template <typename ParameterRequirements>
+ static BOOST_CONSTEXPR typename ParameterRequirements::has_default
+ satisfies(ParameterRequirements*);
+
+ template <typename HasDefault, typename Predicate>
+ static BOOST_CONSTEXPR
+ typename ::boost::mpl::apply_wrap1<Predicate,value_type>::type
+ satisfies(
+ ::boost::parameter::aux::parameter_requirements<
+ key_type
+ , Predicate
+ , HasDefault
+ >*
+ );
+#endif // Function template ordering, Borland workarounds needed.
+
+ // MPL sequence support
+ // Convenience for users
+ typedef ::boost::parameter::aux::tagged_argument<Keyword,Arg> type;
+ // For the benefit of iterators
+ typedef ::boost::parameter::aux::empty_arg_list tail_type;
+ // For dispatching to sequence intrinsics
+ typedef ::boost::parameter::aux::arg_list_tag tag;
+
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
+ // warning suppression
+ private:
+ void operator=(type const&);
+#endif
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename TaggedArg>
+ struct tagged_argument_list_of_1 : public TaggedArg
{
- return x.compute_default();
- }
-
- template <class ParameterRequirements>
- static typename ParameterRequirements::has_default
- satisfies(ParameterRequirements*);
-
- template <class HasDefault, class Predicate>
- static typename mpl::apply1<Predicate, value_type>::type
- satisfies(
- parameter_requirements<key_type,Predicate,HasDefault>*
- );
-# endif
-
- reference value;
-# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
- // warning suppression
- private:
- void operator=(tagged_argument const&);
- public:
-# endif
- // MPL sequence support
- typedef tagged_argument type; // Convenience for users
- typedef empty_arg_list tail_type; // For the benefit of iterators
- typedef arg_list_tag tag; // For dispatching to sequence intrinsics
-};
-
-// Defines a metafunction, is_tagged_argument, that identifies
-// tagged_argument specializations and their derived classes.
-template <class T>
-struct is_tagged_argument_aux
- : is_convertible<T*,tagged_argument_base const*>
-{};
-
-template <class T>
-struct is_tagged_argument
- : mpl::and_<
- mpl::not_<is_reference<T> >
- , is_tagged_argument_aux<T>
- >
-{};
+ using base_type = TaggedArg;
+
+ inline explicit BOOST_CONSTEXPR tagged_argument_list_of_1(
+ typename base_type::reference x
+ ) : base_type(static_cast<typename base_type::reference>(x))
+ {
+ }
+
+ inline BOOST_CONSTEXPR tagged_argument_list_of_1(
+ tagged_argument_list_of_1 const& copy
+ ) : base_type(static_cast<base_type const&>(copy))
+ {
+ }
+
+ using base_type::operator[];
+ using base_type::satisfies;
+ template <typename TA2>
+ inline BOOST_CONSTEXPR ::boost::parameter::aux::flat_like_arg_list<
+ ::boost::parameter::aux
+ ::flat_like_arg_tuple<typename TaggedArg::key_type,TaggedArg>
+ , ::boost::parameter::aux::flat_like_arg_tuple<
+ typename TA2::base_type::key_type
+ , typename TA2::base_type
+ >
+ >
+ operator,(TA2 const& x) const
+ {
+ return boost::parameter::aux::flat_like_arg_list<
+ ::boost::parameter::aux
+ ::flat_like_arg_tuple<typename TaggedArg::key_type,TaggedArg>
+ , ::boost::parameter::aux::flat_like_arg_tuple<
+ typename TA2::base_type::key_type
+ , typename TA2::base_type
+ >
+ >(
+ static_cast<base_type const&>(*this)
+ , ::boost::parameter::aux::arg_list<typename TA2::base_type>(
+ static_cast<typename TA2::base_type const&>(x)
+ , ::boost::parameter::aux::empty_arg_list()
+ )
+ );
+ }
+ };
}}} // namespace boost::parameter::aux
-#endif // BOOST_PARAMETER_TAGGED_ARGUMENT_050328_HPP
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+#endif // include guard
diff --git a/boost/parameter/aux_/tagged_argument_fwd.hpp b/boost/parameter/aux_/tagged_argument_fwd.hpp
new file mode 100644
index 0000000000..5f1e5a1074
--- /dev/null
+++ b/boost/parameter/aux_/tagged_argument_fwd.hpp
@@ -0,0 +1,38 @@
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Copyright Cromwell D. Enage 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_PARAMETER_TAGGED_ARGUMENT_FWD_HPP
+#define BOOST_PARAMETER_TAGGED_ARGUMENT_FWD_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Keyword, typename Arg>
+ class tagged_argument;
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename Keyword, typename Arg>
+ struct tagged_argument_rref;
+}}} // namespace boost::parameter::aux
+
+#endif
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename TaggedArg>
+ struct tagged_argument_list_of_1;
+}}} // namespace boost::parameter::aux
+
+#endif
+#endif // include guard
+
diff --git a/boost/parameter/aux_/template_keyword.hpp b/boost/parameter/aux_/template_keyword.hpp
index 5a02f008a3..ee563f1aa7 100644
--- a/boost/parameter/aux_/template_keyword.hpp
+++ b/boost/parameter/aux_/template_keyword.hpp
@@ -1,47 +1,89 @@
-// Copyright Daniel Wallin 2006. Use, modification and distribution is
-// subject to the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright Daniel Wallin 2006.
+// Copyright Cromwell D. Enage 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_PARAMETER_TEMPLATE_KEYWORD_060203_HPP
-# define BOOST_PARAMETER_TEMPLATE_KEYWORD_060203_HPP
+#define BOOST_PARAMETER_TEMPLATE_KEYWORD_060203_HPP
-# include <boost/mpl/and.hpp>
-# include <boost/mpl/not.hpp>
-# include <boost/type_traits/is_convertible.hpp>
-# include <boost/type_traits/is_reference.hpp>
+namespace boost { namespace parameter { namespace aux {
-namespace boost { namespace parameter {
+ struct template_keyword_base
+ {
+ };
+}}} // namespace boost::parameter::aux
-namespace aux
-{
+#include <boost/parameter/config.hpp>
- struct template_keyword_tag {};
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <type_traits>
- template <class T, class U>
- struct is_pointer_convertible
- : is_convertible<T*, U*>
- {};
+namespace boost { namespace parameter { namespace aux {
- template <class T>
- struct is_template_keyword
- : mpl::and_<
- mpl::not_<is_reference<T> >
- , is_pointer_convertible<T, template_keyword_tag>
- >
- {};
+ template <typename T>
+ using is_template_keyword = ::std::is_base_of<
+ ::boost::parameter::aux::template_keyword_base
+ , typename ::std::remove_const<
+ typename ::std::remove_reference<T>::type
+ >::type
+ >;
+}}} // namespace boost::parameter::aux
-} // namespace aux
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/remove_const.hpp>
-template <class Tag, class T>
-struct template_keyword
- : aux::template_keyword_tag
-{
- typedef Tag key_type;
- typedef T value_type;
- typedef value_type reference;
-};
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#else
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
+#endif
-}} // namespace boost::parameter
+namespace boost { namespace parameter { namespace aux {
-#endif // BOOST_PARAMETER_TEMPLATE_KEYWORD_060203_HPP
+#if !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+ template <typename T>
+ struct is_template_keyword_aux
+ : ::boost::mpl::if_<
+ ::boost::is_convertible<
+ T*
+ , ::boost::parameter::aux::template_keyword_base const*
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >::type
+ {
+ };
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+
+ template <typename T>
+ struct is_template_keyword
+ : ::boost::mpl::if_<
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+ // Cannot use is_convertible<> to check if T is derived from
+ // template_keyword_base. -- Cromwell D. Enage
+ ::boost::is_base_of<
+ ::boost::parameter::aux::template_keyword_base
+ , typename ::boost::remove_const<
+ typename ::boost::remove_reference<T>::type
+ >::type
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+#else
+ ::boost::is_lvalue_reference<T>
+ , ::boost::mpl::false_
+ , ::boost::parameter::aux::is_template_keyword_aux<T>
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+ >::type
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+#endif // include guard
diff --git a/boost/parameter/aux_/unwrap_cv_reference.hpp b/boost/parameter/aux_/unwrap_cv_reference.hpp
index b6c263f232..af577db008 100644
--- a/boost/parameter/aux_/unwrap_cv_reference.hpp
+++ b/boost/parameter/aux_/unwrap_cv_reference.hpp
@@ -1,91 +1,174 @@
-// Copyright Daniel Wallin, David Abrahams 2005. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Copyright Cromwell D. Enage 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 UNWRAP_CV_REFERENCE_050328_HPP
#define UNWRAP_CV_REFERENCE_050328_HPP
+namespace boost {
+
+ template <typename T>
+ class reference_wrapper;
+} // namespace boost
+
#include <boost/parameter/aux_/yesno.hpp>
-#include <boost/mpl/bool.hpp>
-#include <boost/mpl/identity.hpp>
-#include <boost/mpl/eval_if.hpp>
-namespace boost { template<class T> class reference_wrapper; }
+namespace boost { namespace parameter { namespace aux {
+
+ //
+ // reference_wrapper support -- if perfect forwarding is unsupported,
+ // then when passing arguments positionally by non-const reference,
+ // we ask users of named parameter interfaces to use ref(x) to wrap them.
+ //
+
+ template <typename U>
+ ::boost::parameter::aux::yes_tag
+ is_cv_reference_wrapper_check(
+ ::boost::reference_wrapper<U> const volatile*
+ );
+
+ ::boost::parameter::aux::no_tag is_cv_reference_wrapper_check(...);
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/config.hpp>
+
+#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
+#include <functional>
namespace boost { namespace parameter { namespace aux {
-//
-// reference_wrapper support -- because of the forwarding problem,
-// when passing arguments positionally by non-const reference, we
-// ask users of named parameter interfaces to use ref(x) to wrap
-// them.
-//
-
-// is_cv_reference_wrapper returns mpl::true_ if T is of type
-// reference_wrapper<U> cv
-template <class U>
-yes_tag is_cv_reference_wrapper_check(reference_wrapper<U> const volatile*);
-no_tag is_cv_reference_wrapper_check(...);
-
-template <class T>
-struct is_cv_reference_wrapper
-{
- BOOST_STATIC_CONSTANT(
- bool, value = (
- sizeof(is_cv_reference_wrapper_check((T*)0)) == sizeof(yes_tag)
- )
- );
-
- typedef mpl::bool_<
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- is_cv_reference_wrapper::
-#endif
- value> type;
-};
+ // Support for std::ref(x) -- Cromwell D. Enage
+ template <typename U>
+ ::boost::parameter::aux::yes_tag
+ is_cv_reference_wrapper_check(
+ ::std::reference_wrapper<U> const volatile*
+ );
+}}} // namespace boost::parameter::aux
+#endif
-// Needed for unwrap_cv_reference below. T might be const, so
-// eval_if might fail because of deriving from T const on EDG.
-template <class T>
-struct get_type
-{
- typedef typename T::type type;
-};
+#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-template <class T, class is_reference_wrapper = typename is_cv_reference_wrapper<T>::type>
-struct unwrap_cv_reference
-{
- typedef T type;
-};
-
-template <class T>
-struct unwrap_cv_reference<T const, mpl::false_>
-{
- typedef T const type;
-};
-
-template <class T>
-struct unwrap_cv_reference<T, mpl::true_>
- : T
-{};
-
-#else
-// Produces the unwrapped type to hold a reference to in named<>
-// Can't use boost::unwrap_reference<> here because it
-// doesn't handle the case where T = reference_wrapper<U> cv
-template <class T>
-struct unwrap_cv_reference
-{
- typedef typename mpl::eval_if<
- is_cv_reference_wrapper<T>
- , get_type<T>
- , mpl::identity<T>
- >::type type;
-};
+#if defined(BOOST_PARAMETER_CAN_USE_MP11) && !( \
+ BOOST_WORKAROUND(BOOST_MSVC, >= 1900) && \
+ BOOST_WORKAROUND(BOOST_MSVC, < 1910) \
+ )
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11) || MSVC-14.0
+#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
+ !BOOST_WORKAROUND(BOOST_GCC, < 40000)
+#include <boost/mpl/eval_if.hpp>
#endif
+#endif // BOOST_PARAMETER_CAN_USE_MP11 && not MSVC-14.0
+
+namespace boost { namespace parameter { namespace aux {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11) && !( \
+ BOOST_WORKAROUND(BOOST_MSVC, >= 1900) && \
+ BOOST_WORKAROUND(BOOST_MSVC, < 1910) \
+ )
+ // This metafunction returns mp11::mp_true if T is of type
+ // reference_wrapper<U> cv.
+ template <typename T>
+ using is_cv_reference_wrapper = ::boost::mp11::mp_bool<
+ sizeof(
+ ::boost::parameter::aux::is_cv_reference_wrapper_check(
+ static_cast<
+ typename ::std::remove_reference<T>::type*
+ >(BOOST_PARAMETER_AUX_PP_NULLPTR)
+ )
+ ) == sizeof(::boost::parameter::aux::yes_tag)
+ >;
+
+ // Needed for unwrap_cv_reference below. T might be const, so
+ // mp_eval_if<> might fail because of deriving from T const on EDG.
+ template <typename T>
+ using unwrap_cv_reference_impl = typename ::std::remove_reference<T>::type;
+
+ // Produces the unwrapped type to hold a reference to in
+ // tagged_argument<>. Can't use boost::unwrap_reference<> here
+ // because it doesn't handle the case where T = reference_wrapper<U> cv.
+ template <typename T>
+ using unwrap_cv_reference = ::boost::mp11::mp_eval_if<
+ ::boost::parameter::aux::is_cv_reference_wrapper<T>
+ , ::boost::parameter::aux::unwrap_cv_reference_impl<T>
+ , ::std::remove_reference
+ , T
+ >;
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11) || MSVC-14.0
+ // This metafunction returns mpl::true_ if T is of type
+ // reference_wrapper<U> cv.
+ template <typename T>
+ struct is_cv_reference_wrapper
+ {
+ BOOST_STATIC_CONSTANT(
+ bool, value = (
+ sizeof(
+ ::boost::parameter::aux::is_cv_reference_wrapper_check(
+ static_cast<
+ typename ::boost::remove_reference<T>::type*
+ >(BOOST_PARAMETER_AUX_PP_NULLPTR)
+ )
+ ) == sizeof(::boost::parameter::aux::yes_tag)
+ )
+ );
+
+ typedef boost::mpl::bool_<
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ is_cv_reference_wrapper::
+#endif
+ value> type;
+ };
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \
+ BOOST_WORKAROUND(BOOST_GCC, < 40000)
+ template <
+ typename T
+ , typename = typename ::boost::parameter::aux
+ ::is_cv_reference_wrapper<T>::type
+ >
+ struct unwrap_cv_reference : ::boost::remove_reference<T>
+ {
+ };
+
+ template <typename T>
+ struct unwrap_cv_reference<T const,::boost::mpl::false_>
+ {
+ typedef T const type;
+ };
+
+ template <typename T>
+ struct unwrap_cv_reference<T,::boost::mpl::true_> : T
+ {
+ };
+#else // no Borland or GCC 3- workarounds needed
+ // Needed for unwrap_cv_reference below. T might be const, so
+ // eval_if<> might fail because of deriving from T const on EDG.
+ template <typename T>
+ struct unwrap_cv_reference_impl : ::boost::remove_reference<T>::type
+ {
+ };
+
+ // Produces the unwrapped type to hold a reference to in
+ // tagged_argument<>. Can't use boost::unwrap_reference<> here
+ // because it doesn't handle the case where T = reference_wrapper<U> cv.
+ template <typename T>
+ struct unwrap_cv_reference
+ : ::boost::mpl::eval_if<
+ ::boost::parameter::aux::is_cv_reference_wrapper<T>
+ , ::boost::parameter::aux::unwrap_cv_reference_impl<T>
+ , ::boost::remove_reference<T>
+ >
+ {
+ };
+#endif // Borland or GCC 3- workarounds needed
+#endif // BOOST_PARAMETER_CAN_USE_MP11 && not MSVC-14.0
}}} // namespace boost::parameter::aux
-#endif // UNWRAP_CV_REFERENCE_050328_HPP
+#endif // include guard
diff --git a/boost/parameter/aux_/use_default.hpp b/boost/parameter/aux_/use_default.hpp
new file mode 100644
index 0000000000..ba25a3f3de
--- /dev/null
+++ b/boost/parameter/aux_/use_default.hpp
@@ -0,0 +1,17 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_AUX_USE_DEFAULT_HPP
+#define BOOST_PARAMETER_AUX_USE_DEFAULT_HPP
+
+namespace boost { namespace parameter { namespace aux {
+
+ struct use_default
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/use_default_tag.hpp b/boost/parameter/aux_/use_default_tag.hpp
new file mode 100644
index 0000000000..54db947a90
--- /dev/null
+++ b/boost/parameter/aux_/use_default_tag.hpp
@@ -0,0 +1,29 @@
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_USE_DEFAULT_TAG_HPP
+#define BOOST_PARAMETER_USE_DEFAULT_TAG_HPP
+
+#include <boost/config.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+
+ struct use_default_tag
+ {
+ inline BOOST_CONSTEXPR BOOST_DEFAULTED_FUNCTION(use_default_tag(), {})
+
+ inline BOOST_CONSTEXPR BOOST_DEFAULTED_FUNCTION(
+ use_default_tag(use_default_tag const&), {}
+ )
+
+ inline BOOST_CONSTEXPR use_default_tag operator()() const
+ {
+ return *this;
+ }
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/aux_/void.hpp b/boost/parameter/aux_/void.hpp
index 7061a7deb5..2c7103b3e4 100644
--- a/boost/parameter/aux_/void.hpp
+++ b/boost/parameter/aux_/void.hpp
@@ -1,6 +1,6 @@
-// Copyright Daniel Wallin, David Abrahams 2005. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARAMETER_VOID_050329_HPP
@@ -8,22 +8,31 @@
namespace boost { namespace parameter {
-// A placemarker for "no argument passed."
-// MAINTAINER NOTE: Do not make this into a metafunction
-struct void_ {};
+ // A placemarker for "no argument passed."
+ // MAINTAINER NOTE: Do not make this into a metafunction
+ struct void_
+ {
+ };
+}} // namespace boost::parameter
-namespace aux
-{
+namespace boost { namespace parameter { namespace aux {
- inline void_& void_reference()
- {
- static void_ instance;
- return instance;
- }
+ inline ::boost::parameter::void_& void_reference()
+ {
+ static ::boost::parameter::void_ instance;
+ return instance;
+ }
+}}} // namespace boost::parameter::aux
-} // namespace aux
+#include <boost/config/workaround.hpp>
-}} // namespace boost::parameter
+#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580))
+
+namespace boost { namespace parameter { namespace aux {
+
+ typedef void* voidstar;
+}}} // namespace boost::parameter::aux
-#endif // BOOST_PARAMETER_VOID_050329_HPP
+#endif
+#endif // include guard
diff --git a/boost/parameter/aux_/yesno.hpp b/boost/parameter/aux_/yesno.hpp
index 13fa545a68..583c64abbc 100644
--- a/boost/parameter/aux_/yesno.hpp
+++ b/boost/parameter/aux_/yesno.hpp
@@ -1,26 +1,42 @@
-// Copyright Daniel Wallin, David Abrahams 2005. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef YESNO_050328_HPP
#define YESNO_050328_HPP
+namespace boost { namespace parameter { namespace aux {
+
+ // types used with the "sizeof trick" to capture the results of
+ // overload resolution at compile-time.
+ typedef char yes_tag;
+ typedef char (&no_tag)[2];
+}}} // namespace boost::parameter::aux
+
#include <boost/mpl/bool.hpp>
namespace boost { namespace parameter { namespace aux {
-// types used with the "sizeof trick" to capture the results of
-// overload resolution at compile-time.
-typedef char yes_tag;
-typedef char (&no_tag)[2];
+ // mpl::true_ and mpl::false_ are not distinguishable by sizeof(),
+ // so we pass them through these functions to get a type that is.
+ ::boost::parameter::aux::yes_tag to_yesno(::boost::mpl::true_);
+ ::boost::parameter::aux::no_tag to_yesno(::boost::mpl::false_);
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/config.hpp>
-// mpl::true_ and mpl::false_ are not distinguishable by sizeof(),
-// so we pass them through these functions to get a type that is.
-yes_tag to_yesno(mpl::true_);
-no_tag to_yesno(mpl::false_);
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+
+namespace boost { namespace parameter { namespace aux {
+ // mp11::mp_true and mp11::mp_false are not distinguishable by sizeof(),
+ // so we pass them through these functions to get a type that is.
+ ::boost::parameter::aux::yes_tag to_yesno(::boost::mp11::mp_true);
+ ::boost::parameter::aux::no_tag to_yesno(::boost::mp11::mp_false);
}}} // namespace boost::parameter::aux
-#endif // YESNO_050328_HPP
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+#endif // include guard
diff --git a/boost/parameter/binding.hpp b/boost/parameter/binding.hpp
index 778a7b7bac..a1d4e85ce0 100644
--- a/boost/parameter/binding.hpp
+++ b/boost/parameter/binding.hpp
@@ -1,80 +1,164 @@
-// Copyright David Abrahams 2005. Distributed under the 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 David Abrahams 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
#ifndef BOOST_PARAMETER_BINDING_DWA200558_HPP
-# define BOOST_PARAMETER_BINDING_DWA200558_HPP
+#define BOOST_PARAMETER_BINDING_DWA200558_HPP
+
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/parameter/config.hpp>
-# include <boost/mpl/apply.hpp>
-# include <boost/mpl/assert.hpp>
-# include <boost/mpl/and.hpp>
-# include <boost/parameter/aux_/result_of0.hpp>
-# include <boost/parameter/aux_/void.hpp>
-# include <boost/type_traits/is_same.hpp>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#endif
namespace boost { namespace parameter {
-// A metafunction that, given an argument pack, returns the type of
-// the parameter identified by the given keyword. If no such
-// parameter has been specified, returns Default
-
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-template <class Parameters, class Keyword, class Default>
-struct binding0
-{
- typedef typename mpl::apply_wrap3<
- typename Parameters::binding,Keyword,Default,mpl::true_
- >::type type;
-
- BOOST_MPL_ASSERT_NOT((
- mpl::and_<
- is_same<Default, void_>
- , is_same<type, void_>
- >
- ));
-};
-# endif
-
-template <class Parameters, class Keyword, class Default = void_>
-struct binding
-{
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- typedef typename mpl::eval_if<
- mpl::is_placeholder<Parameters>
- , mpl::identity<int>
- , binding0<Parameters,Keyword,Default>
- >::type type;
-# else
- typedef typename mpl::apply_wrap3<
- typename Parameters::binding,Keyword,Default,mpl::true_
- >::type type;
-
- BOOST_MPL_ASSERT_NOT((
- mpl::and_<
- is_same<Default, void_>
- , is_same<type, void_>
+ // A metafunction that, given an argument pack, returns the reference type
+ // of the parameter identified by the given keyword. If no such parameter
+ // has been specified, returns Default
+
+ template <typename Parameters, typename Keyword, typename Default>
+ struct binding0
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_apply_q<
+ typename Parameters::binding
+ , ::boost::mp11::mp_list<Keyword,Default,::boost::mp11::mp_true>
+ >;
+
+ static_assert(
+ ::boost::mp11::mp_if<
+ ::std::is_same<Default,::boost::parameter::void_>
+ , ::boost::mp11::mp_if<
+ ::std::is_same<type,::boost::parameter::void_>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ , ::boost::mp11::mp_true
+ >::value
+ , "required parameters must not result in void_ type"
+ );
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typedef typename ::boost::mpl::apply_wrap3<
+ typename Parameters::binding
+ , Keyword
+ , Default
+ , ::boost::mpl::true_
+ >::type type;
+
+ BOOST_MPL_ASSERT((
+ typename ::boost::mpl::eval_if<
+ ::boost::is_same<Default,::boost::parameter::void_>
+ , ::boost::mpl::if_<
+ ::boost::is_same<type,::boost::parameter::void_>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::true_
+ >::type
+ ));
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename Placeholder, typename Keyword, typename Default>
+ struct binding1
+ {
+ using type = ::boost::mp11::mp_apply_q<
+ Placeholder
+ , ::boost::mp11::mp_list<Keyword,Default,::boost::mp11::mp_true>
+ >;
+
+ static_assert(
+ ::boost::mp11::mp_if<
+ ::std::is_same<Default,::boost::parameter::void_>
+ , ::boost::mp11::mp_if<
+ ::std::is_same<type,::boost::parameter::void_>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ , ::boost::mp11::mp_true
+ >::value
+ , "required parameters must not result in void_ type"
+ );
+ };
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}} // namespace boost::parameter
+
+#include <boost/parameter/aux_/is_placeholder.hpp>
+
+namespace boost { namespace parameter {
+
+ template <
+ typename Parameters
+ , typename Keyword
+ , typename Default = ::boost::parameter::void_
+ >
+ struct binding
+#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mpl::eval_if<
+ ::boost::parameter::aux::is_mpl_placeholder<Parameters>
+ , ::boost::mpl::identity<int>
+ , ::boost::parameter::binding0<Parameters,Keyword,Default>
>
- ));
-# endif
-
- BOOST_MPL_AUX_LAMBDA_SUPPORT(3,binding,(Parameters,Keyword,Default))
-};
-
-// A metafunction that, given an argument pack, returns the type of
-// the parameter identified by the given keyword. If no such
-// parameter has been specified, returns the type returned by invoking
-// DefaultFn
-template <class Parameters, class Keyword, class DefaultFn>
-struct lazy_binding
-{
- typedef typename mpl::apply_wrap3<
- typename Parameters::binding
- , Keyword
- , typename aux::result_of0<DefaultFn>::type
- , mpl::true_
- >::type type;
-};
+#endif
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = typename ::boost::mp11::mp_if<
+ ::boost::parameter::aux::is_mpl_placeholder<Parameters>
+ , ::boost::mp11::mp_identity<int>
+ , ::boost::mp11::mp_if<
+ ::boost::parameter::aux::is_mp11_placeholder<Parameters>
+ , ::boost::parameter::binding1<Parameters,Keyword,Default>
+ , ::boost::parameter::binding0<Parameters,Keyword,Default>
+ >
+ >::type;
+#endif
+ };
+}} // namespace boost::parameter
+
+#include <boost/parameter/aux_/result_of0.hpp>
+namespace boost { namespace parameter {
+ // A metafunction that, given an argument pack, returns the reference type
+ // of the parameter identified by the given keyword. If no such parameter
+ // has been specified, returns the type returned by invoking DefaultFn
+ template <typename Parameters, typename Keyword, typename DefaultFn>
+ struct lazy_binding
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_apply_q<
+ typename Parameters::binding
+ , ::boost::mp11::mp_list<
+ Keyword
+ , typename ::boost::parameter::aux::result_of0<DefaultFn>::type
+ , ::boost::mp11::mp_true
+ >
+ >;
+#else
+ typedef typename ::boost::mpl::apply_wrap3<
+ typename Parameters::binding
+ , Keyword
+ , typename ::boost::parameter::aux::result_of0<DefaultFn>::type
+ , ::boost::mpl::true_
+ >::type type;
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ };
}} // namespace boost::parameter
-#endif // BOOST_PARAMETER_BINDING_DWA200558_HPP
+#endif // include guard
+
diff --git a/boost/parameter/compose.hpp b/boost/parameter/compose.hpp
new file mode 100644
index 0000000000..a1111989ea
--- /dev/null
+++ b/boost/parameter/compose.hpp
@@ -0,0 +1,210 @@
+// Copyright Cromwell D. Enage 2019.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_COMPOSE_HPP
+#define BOOST_PARAMETER_COMPOSE_HPP
+
+#include <boost/parameter/aux_/arg_list.hpp>
+
+namespace boost { namespace parameter {
+
+ inline BOOST_CONSTEXPR ::boost::parameter::aux::empty_arg_list compose()
+ {
+ return ::boost::parameter::aux::empty_arg_list();
+ }
+}} // namespace boost::parameter
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+namespace boost { namespace parameter { namespace aux {
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename ...TaggedArgs>
+ struct compose_arg_list
+ {
+ using type = ::boost::parameter::aux::flat_like_arg_list<
+ ::boost::parameter::aux::flat_like_arg_tuple<
+ typename TaggedArgs::base_type::key_type
+ , typename TaggedArgs::base_type
+ >...
+ >;
+ };
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename TaggedArg0, typename ...TaggedArgs>
+ struct compose_arg_list;
+
+ template <typename TaggedArg0>
+ struct compose_arg_list<TaggedArg0>
+ {
+ typedef ::boost::parameter::aux::arg_list<TaggedArg0> type;
+ };
+
+ template <typename TaggedArg0, typename ...TaggedArgs>
+ struct compose_arg_list
+ {
+ typedef ::boost::parameter::aux::arg_list<
+ TaggedArg0
+ , typename ::boost::parameter::aux
+ ::compose_arg_list<TaggedArgs...>::type
+ > type;
+ };
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/are_tagged_arguments.hpp>
+#include <boost/core/enable_if.hpp>
+
+namespace boost { namespace parameter { namespace result_of {
+
+ template <typename ...TaggedArgs>
+ struct compose
+ : ::boost::lazy_enable_if<
+ ::boost::parameter::are_tagged_arguments<TaggedArgs...>
+ , ::boost::parameter::aux::compose_arg_list<TaggedArgs...>
+ >
+ {
+ };
+
+ template <>
+ struct compose<>
+ {
+ typedef ::boost::parameter::aux::empty_arg_list type;
+ };
+}}} // namespace boost::parameter::result_of
+
+namespace boost { namespace parameter {
+
+ template <typename TaggedArg0, typename ...TaggedArgs>
+ inline BOOST_CONSTEXPR typename ::boost::parameter::result_of
+ ::compose<TaggedArg0,TaggedArgs...>::type
+ compose(TaggedArg0 const& arg0, TaggedArgs const&... args)
+ {
+ return typename ::boost::parameter::aux
+ ::compose_arg_list<TaggedArg0,TaggedArgs...>::type(
+ ::boost::parameter::aux::value_type_is_not_void()
+ , arg0
+ , args...
+ );
+ }
+}} // namespace boost::parameter
+
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+#define BOOST_PARAMETER_compose_arg_list_type_suffix(z, n, suffix) suffix
+
+#include <boost/preprocessor/cat.hpp>
+
+#define BOOST_PARAMETER_compose_arg_list_type_prefix(z, n, prefix) \
+ ::boost::parameter::aux::arg_list<BOOST_PP_CAT(prefix, n)
+/**/
+
+#include <boost/preprocessor/facilities/intercept.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+
+#define BOOST_PARAMETER_compose_arg_list_type(z, n, prefix) \
+ BOOST_PP_CAT(BOOST_PP_ENUM_, z)( \
+ n, BOOST_PARAMETER_compose_arg_list_type_prefix, prefix \
+ ) BOOST_PP_CAT(BOOST_PP_REPEAT_, z)( \
+ n, BOOST_PARAMETER_compose_arg_list_type_suffix, > \
+ )
+/**/
+
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+
+#if defined(BOOST_NO_SFINAE)
+#define BOOST_PARAMETER_compose_arg_list_function_overload(z, n, prefix) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename prefix)> \
+ inline BOOST_CONSTEXPR \
+ BOOST_PARAMETER_compose_arg_list_type(z, n, prefix) \
+ compose(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, prefix, const& a)) \
+ { \
+ return BOOST_PARAMETER_compose_arg_list_type(z, n, prefix)( \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
+ BOOST_PP_ENUM_TRAILING_PARAMS_Z( \
+ z \
+ , BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, n) \
+ , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT \
+ ) \
+ ); \
+ }
+/**/
+#else // !defined(BOOST_NO_SFINAE)
+#include <boost/parameter/are_tagged_arguments.hpp>
+#include <boost/core/enable_if.hpp>
+
+namespace boost { namespace parameter { namespace result_of {
+
+ template <
+ BOOST_PP_ENUM_BINARY_PARAMS(
+ BOOST_PP_INC(BOOST_PARAMETER_COMPOSE_MAX_ARITY)
+ , typename TaggedArg
+ , = void BOOST_PP_INTERCEPT
+ )
+ >
+ struct compose;
+
+ template <>
+ struct compose<>
+ {
+ typedef ::boost::parameter::aux::empty_arg_list type;
+ };
+}}} // namespace boost::parameter::result_of
+
+#define BOOST_PARAMETER_compose_arg_list_function_overload(z, n, prefix) \
+namespace boost { namespace parameter { namespace result_of { \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename prefix)> \
+ struct compose<BOOST_PP_ENUM_PARAMS_Z(z, n, prefix)> \
+ : ::boost::enable_if< \
+ ::boost::parameter \
+ ::are_tagged_arguments<BOOST_PP_ENUM_PARAMS_Z(z, n, prefix)> \
+ , BOOST_PARAMETER_compose_arg_list_type(z, n, prefix) \
+ > \
+ { \
+ }; \
+}}} \
+namespace boost { namespace parameter { \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename prefix)> \
+ inline BOOST_CONSTEXPR typename ::boost::parameter::result_of \
+ ::compose<BOOST_PP_ENUM_PARAMS_Z(z, n, prefix)>::type \
+ compose(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, prefix, const& a)) \
+ { \
+ return BOOST_PARAMETER_compose_arg_list_type(z, n, prefix)( \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
+ BOOST_PP_ENUM_TRAILING_PARAMS_Z( \
+ z \
+ , BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, n) \
+ , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT \
+ ) \
+ ); \
+ } \
+}}
+/**/
+#endif // BOOST_NO_SFINAE
+
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+BOOST_PP_REPEAT_FROM_TO(
+ 1
+ , BOOST_PP_INC(BOOST_PARAMETER_COMPOSE_MAX_ARITY)
+ , BOOST_PARAMETER_compose_arg_list_function_overload
+ , TaggedArg
+)
+
+#undef BOOST_PARAMETER_compose_arg_list_function_overload
+#undef BOOST_PARAMETER_compose_arg_list_type
+#undef BOOST_PARAMETER_compose_arg_list_type_prefix
+#undef BOOST_PARAMETER_compose_arg_list_type_suffix
+
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+#endif // include guard
+
diff --git a/boost/parameter/config.hpp b/boost/parameter/config.hpp
index 5710c92c0a..1b738f1fb6 100644
--- a/boost/parameter/config.hpp
+++ b/boost/parameter/config.hpp
@@ -1,14 +1,83 @@
-// Copyright Daniel Wallin, David Abrahams 2005. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Copyright Cromwell D. Enage 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_PARAMETER_CONFIG_050403_HPP
#define BOOST_PARAMETER_CONFIG_050403_HPP
-#ifndef BOOST_PARAMETER_MAX_ARITY
-# define BOOST_PARAMETER_MAX_ARITY 8
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+// Allow projects to #define BOOST_PARAMETER_DISABLE_PERFECT_FORWARDING to
+// turn off perfect forwarding as necessary. Otherwise, also require correct
+// SFINAE support, needed explicitly by tagged_argument & keyword & cast;
+// correct function template ordering, needed by the code generation macros;
+// rvalue references, needed throughout; variadic templates, needed by
+// parameters; function template default arguments, needed by the code
+// generation macros; and the ability to handle multiple parameter packs,
+// needed by parameters. Older versions of GCC either don't have the latter
+// ability or cannot disambiguate between keyword's overloaded
+// operators. Older versions of Clang either fail to compile due to
+// differences in length between parameter packs 'Args' and 'args' or fail at
+// runtime due to segmentation faults.
+// -- Cromwell D. Enage
+#if !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) && \
+ !defined(BOOST_PARAMETER_DISABLE_PERFECT_FORWARDING) && \
+ !defined(BOOST_NO_SFINAE) && \
+ !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) && \
+ !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \
+ !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && !( \
+ defined(BOOST_CLANG) && (1 == BOOST_CLANG) && ( \
+ (__clang_major__ < 3) || ( \
+ (3 == __clang_major__) && (__clang_minor__ < 2) \
+ ) \
+ ) \
+ ) && !BOOST_WORKAROUND(BOOST_GCC, < 40900)
+#define BOOST_PARAMETER_HAS_PERFECT_FORWARDING
#endif
-#endif // BOOST_PARAMETER_CONFIG_050403_HPP
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#if !defined(BOOST_PARAMETER_CAN_USE_MP11) && \
+ !defined(BOOST_PARAMETER_DISABLE_MP11_USAGE) && \
+ !defined(BOOST_NO_CXX11_CONSTEXPR) && \
+ !defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
+ !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && \
+ !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \
+ !defined(BOOST_NO_CXX11_STATIC_ASSERT) && \
+ !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) && \
+ !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) && \
+ !defined(BOOST_NO_CXX11_HDR_TUPLE)
+// Boost.MP11 requires C++11. -- Cromwell D. Enage
+#define BOOST_PARAMETER_CAN_USE_MP11
+#endif
+#if !defined(BOOST_PARAMETER_MAX_ARITY)
+// Unlike the variadic MPL sequences provided by Boost.Fusion,
+// boost::mpl::vector has a size limit. -- Cromwell D. Enage
+#include <boost/mpl/limits/vector.hpp>
+#define BOOST_PARAMETER_MAX_ARITY BOOST_MPL_LIMIT_VECTOR_SIZE
+#endif
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#if !defined(BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY)
+#define BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY 0
+#endif
+#if !defined(BOOST_PARAMETER_COMPOSE_MAX_ARITY)
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1800) || \
+ BOOST_WORKAROUND(BOOST_GCC, < 60000)
+// Some tests cause MSVC-11.0 and earlier to run out of heap space,
+// while some other tests cause GCC 5 and earlier to do the same,
+// if the value is set any higher. -- Cromwell D. Enage
+#define BOOST_PARAMETER_COMPOSE_MAX_ARITY 20
+#else
+#define BOOST_PARAMETER_COMPOSE_MAX_ARITY 64
+#endif
+#endif // BOOST_PARAMETER_COMPOSE_MAX_ARITY
+#if !defined(BOOST_PARAMETER_MAX_ARITY)
+#define BOOST_PARAMETER_MAX_ARITY 8
+#endif
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+#endif // include guard
diff --git a/boost/parameter/deduced.hpp b/boost/parameter/deduced.hpp
new file mode 100644
index 0000000000..518ac799f6
--- /dev/null
+++ b/boost/parameter/deduced.hpp
@@ -0,0 +1,132 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_DEDUCED_HPP
+#define BOOST_PARAMETER_DEDUCED_HPP
+
+#include <boost/parameter/aux_/use_default.hpp>
+
+namespace boost { namespace parameter {
+
+ // This metafunction can be used to describe the treatment of particular
+ // named parameters for the purposes of overload elimination with SFINAE,
+ // by placing specializations in the parameters<...> list.
+ //
+ // If a keyword k is specified with deduced<...>, that keyword
+ // will be automatically deduced from the argument list.
+ template <typename Tag>
+ struct deduced
+ {
+ typedef Tag key_type;
+ };
+}}
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#else
+#include <boost/mpl/bool.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ struct is_deduced_aux
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_false
+#else
+ : ::boost::mpl::false_
+#endif
+ {
+ };
+
+ template <typename Tag>
+ struct is_deduced_aux< ::boost::parameter::deduced<Tag> >
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_true
+#else
+ : ::boost::mpl::true_
+#endif
+ {
+ };
+
+ template <typename T>
+ struct is_deduced0
+ : ::boost::parameter::aux::is_deduced_aux<typename T::key_type>::type
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#include <boost/parameter/required.hpp>
+#include <boost/parameter/optional.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/utility.hpp>
+#else
+#include <boost/mpl/if.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ //
+ // tag_type, has_default, and predicate --
+ //
+ // These metafunctions accept a ParameterSpec and extract the
+ // keyword tag, whether or not a default is supplied for the
+ // parameter, and the predicate that the corresponding actual
+ // argument type is required match.
+ //
+ // a ParameterSpec is a specialization of either keyword<...>,
+ // required<...>, optional<...>
+ //
+
+ template <typename T>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using has_default = ::boost::mp11::mp_if<
+ ::boost::parameter::aux::is_required<T>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >;
+#else
+ struct has_default
+ : ::boost::mpl::if_<
+ ::boost::parameter::aux::is_required<T>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >::type
+ {
+ };
+#endif
+
+ template <typename T>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using is_deduced = ::boost::mp11::mp_if<
+ ::boost::mp11::mp_if<
+ ::boost::parameter::aux::is_optional<T>
+ , ::boost::mp11::mp_true
+ , ::boost::parameter::aux::is_required<T>
+ >
+ , ::boost::parameter::aux::is_deduced0<T>
+ , ::boost::mp11::mp_false
+ >;
+#else
+ struct is_deduced
+ : ::boost::mpl::if_<
+ typename ::boost::mpl::if_<
+ ::boost::parameter::aux::is_optional<T>
+ , ::boost::mpl::true_
+ , ::boost::parameter::aux::is_required<T>
+ >::type
+ , ::boost::parameter::aux::is_deduced0<T>
+ , ::boost::mpl::false_
+ >::type
+ {
+ };
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/is_argument_pack.hpp b/boost/parameter/is_argument_pack.hpp
new file mode 100644
index 0000000000..3ff0d4d7d9
--- /dev/null
+++ b/boost/parameter/is_argument_pack.hpp
@@ -0,0 +1,29 @@
+// Copyright Cromwell D. Enage 2018.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_IS_ARGUMENT_PACK_HPP
+#define BOOST_PARAMETER_IS_ARGUMENT_PACK_HPP
+
+#include <boost/parameter/aux_/is_tagged_argument.hpp>
+#include <boost/parameter/aux_/arg_list.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+
+namespace boost { namespace parameter {
+
+ template <typename T>
+ struct is_argument_pack
+ : ::boost::mpl::if_<
+ ::boost::is_base_of< ::boost::parameter::aux::empty_arg_list,T>
+ , ::boost::mpl::true_
+ , ::boost::parameter::aux::is_tagged_argument<T>
+ >::type
+ {
+ };
+}}
+
+#endif // include guard
+
diff --git a/boost/parameter/keyword.hpp b/boost/parameter/keyword.hpp
index 925c772085..ce792f1a79 100644
--- a/boost/parameter/keyword.hpp
+++ b/boost/parameter/keyword.hpp
@@ -1,122 +1,744 @@
-// Copyright Daniel Wallin, David Abrahams 2005. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
+// Copyright Daniel Wallin, David Abrahams 2005.
+// Copyright Cromwell D. Enage 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 KEYWORD_050328_HPP
#define KEYWORD_050328_HPP
-#include <boost/parameter/aux_/unwrap_cv_reference.hpp>
#include <boost/parameter/aux_/tag.hpp>
#include <boost/parameter/aux_/default.hpp>
+#include <boost/parameter/keyword_fwd.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#include <boost/core/enable_if.hpp>
+#include <utility>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_scalar.hpp>
+#include <boost/type_traits/is_const.hpp>
+#endif
namespace boost { namespace parameter {
-// Instances of unique specializations of keyword<...> serve to
-// associate arguments with parameter names. For example:
-//
-// struct rate_; // parameter names
-// struct skew_;
-// namespace
-// {
-// keyword<rate_> rate; // keywords
-// keyword<skew_> skew;
-// }
-//
-// ...
-//
-// f(rate = 1, skew = 2.4);
-//
-template <class Tag>
-struct keyword
-{
- template <class T>
- typename aux::tag<Tag, T>::type const
- operator=(T& x) const
+ // Instances of unique specializations of keyword<...> serve to
+ // associate arguments with parameter names. For example:
+ //
+ // struct rate_; // parameter names
+ // struct skew_;
+ //
+ // namespace
+ // {
+ // keyword<rate_> rate; // keywords
+ // keyword<skew_> skew;
+ // }
+ //
+ // ...
+ //
+ // f(rate = 1, skew = 2.4);
+ template <typename Tag>
+ struct keyword
{
- typedef typename aux::tag<Tag, T>::type result;
- return result(x);
- }
+ typedef Tag tag;
- template <class Default>
- aux::default_<Tag, Default>
- operator|(Default& default_) const
- {
- return aux::default_<Tag, Default>(default_);
- }
+ inline BOOST_CONSTEXPR keyword()
+ {
+ }
- template <class Default>
- aux::lazy_default<Tag, Default>
- operator||(Default& default_) const
- {
- return aux::lazy_default<Tag, Default>(default_);
- }
+ template <typename T>
+ inline BOOST_CONSTEXPR typename ::boost::lazy_enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::std::is_scalar<T>
+ , ::boost::mp11::mp_true
+ , ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::in_reference
+ >
+ , ::boost::mp11::mp_true
+ , ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >
+ >
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typename ::boost::mpl::eval_if<
+ ::boost::is_scalar<T>
+ , ::boost::mpl::true_
+ , ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::in_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >
+ >
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , ::boost::parameter::aux::tag<Tag,T const&>
+ >::type
+ operator=(T const& x) const
+ {
+ typedef typename ::boost::parameter::aux
+ ::tag<Tag,T const&>::type result;
+ return result(x);
+ }
- template <class T>
- typename aux::tag<Tag, T const>::type const
- operator=(T const& x) const
- {
- typedef typename aux::tag<Tag, T const>::type result;
- return result(x);
- }
+ template <typename Default>
+ inline BOOST_CONSTEXPR typename ::boost::enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::std::is_scalar<Default>
+ , ::boost::mp11::mp_true
+ , ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::in_reference
+ >
+ , ::boost::mp11::mp_true
+ , ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >
+ >
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typename ::boost::mpl::eval_if<
+ ::boost::is_scalar<Default>
+ , ::boost::mpl::true_
+ , ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::in_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >
+ >
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , ::boost::parameter::aux::default_<Tag,Default const>
+ >::type
+ operator|(Default const& d) const
+ {
+ return ::boost::parameter::aux::default_<Tag,Default const>(d);
+ }
- template <class Default>
- aux::default_<Tag, const Default>
- operator|(const Default& default_) const
- {
- return aux::default_<Tag, const Default>(default_);
- }
+ template <typename T>
+ inline BOOST_CONSTEXPR typename ::boost::lazy_enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::mp11::mp_true
+ , ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >
+ , ::boost::mp11::mp_if<
+ ::std::is_const<T>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ , ::boost::mp11::mp_false
+ >
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typename ::boost::mpl::eval_if<
+ typename ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >::type
+ , ::boost::mpl::if_<
+ ::boost::is_const<T>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::false_
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , ::boost::parameter::aux::tag<Tag,T&>
+ >::type
+ operator=(T& x) const
+ {
+ typedef typename ::boost::parameter::aux
+ ::tag<Tag,T&>::type result;
+ return result(x);
+ }
- template <class Default>
- aux::lazy_default<Tag, Default>
- operator||(Default const& default_) const
- {
- return aux::lazy_default<Tag, Default>(default_);
- }
+ template <typename Default>
+ inline BOOST_CONSTEXPR typename ::boost::enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::mp11::mp_true
+ , ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >
+ , ::boost::mp11::mp_if<
+ ::std::is_const<Default>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ , ::boost::mp11::mp_false
+ >
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typename ::boost::mpl::eval_if<
+ typename ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >::type
+ , ::boost::mpl::if_<
+ ::boost::is_const<Default>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::false_
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , ::boost::parameter::aux::default_<Tag,Default>
+ >::type
+ operator|(Default& d) const
+ {
+ return ::boost::parameter::aux::default_<Tag,Default>(d);
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR
+ ::boost::parameter::aux::lazy_default<Tag,Default const>
+ operator||(Default const& d) const
+ {
+ return ::boost::parameter::aux
+ ::lazy_default<Tag,Default const>(d);
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR
+ ::boost::parameter::aux::lazy_default<Tag,Default>
+ operator||(Default& d) const
+ {
+ return ::boost::parameter::aux::lazy_default<Tag,Default>(d);
+ }
+
+ template <typename T>
+ inline BOOST_CONSTEXPR typename ::boost::lazy_enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::std::is_scalar<T>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::in_reference
+ >
+ , ::boost::mp11::mp_true
+ , ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >
+ >
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typename ::boost::mpl::eval_if<
+ ::boost::is_scalar<T>
+ , ::boost::mpl::false_
+ , ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::in_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >
+ >
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , ::boost::parameter::aux::tag<Tag,T const>
+ >::type
+ operator=(T const&& x) const
+ {
+ typedef typename ::boost::parameter::aux
+ ::tag<Tag,T const>::type result;
+ return result(::std::forward<T const>(x));
+ }
+
+ template <typename T>
+ inline BOOST_CONSTEXPR typename ::boost::lazy_enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::std::is_scalar<T>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::consume_reference
+ >
+ , ::boost::mp11::mp_true
+ , ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >
+ >
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typename ::boost::mpl::eval_if<
+ ::boost::is_scalar<T>
+ , ::boost::mpl::false_
+ , ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::consume_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >
+ >
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , ::boost::parameter::aux::tag<Tag,T>
+ >::type
+ operator=(T&& x) const
+ {
+ typedef typename ::boost::parameter::aux::tag<Tag,T>::type result;
+ return result(::std::forward<T>(x));
+ }
- public: // Insurance against ODR violations
-
- // People will need to define these keywords in header files. To
- // prevent ODR violations, it's important that the keyword used in
- // every instantiation of a function template is the same object.
- // We provide a reference to a common instance of each keyword
- // object and prevent construction by users.
- static keyword<Tag> const instance;
-
- // This interface is deprecated
- static keyword<Tag>& get()
+ template <typename Default>
+ inline BOOST_CONSTEXPR typename ::boost::enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::std::is_scalar<Default>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::in_reference
+ >
+ , ::boost::mp11::mp_true
+ , ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >
+ >
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typename ::boost::mpl::eval_if<
+ ::boost::is_scalar<Default>
+ , ::boost::mpl::false_
+ , ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::in_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >
+ >
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , ::boost::parameter::aux::default_r_<Tag,Default const>
+ >::type
+ operator|(Default const&& d) const
+ {
+ return ::boost::parameter::aux::default_r_<Tag,Default const>(
+ ::std::forward<Default const>(d)
+ );
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR typename ::boost::enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::std::is_scalar<Default>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_if<
+ ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::consume_reference
+ >
+ , ::boost::mp11::mp_true
+ , ::std::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >
+ >
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typename ::boost::mpl::eval_if<
+ ::boost::is_scalar<Default>
+ , ::boost::mpl::false_
+ , ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::consume_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >
+ >
+ >::type
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ , ::boost::parameter::aux::default_r_<Tag,Default>
+ >::type
+ operator|(Default&& d) const
+ {
+ return ::boost::parameter::aux
+ ::default_r_<Tag,Default>(::std::forward<Default>(d));
+ }
+
+ public: // Insurance against ODR violations
+ // Users will need to define their keywords in header files. To
+ // prevent ODR violations, it's important that the keyword used in
+ // every instantiation of a function template is the same object.
+ // We provide a reference to a common instance of each keyword
+ // object and prevent construction by users.
+ static ::boost::parameter::keyword<Tag> const instance;
+
+ // This interface is deprecated.
+ static ::boost::parameter::keyword<Tag>& get()
+ {
+ return const_cast< ::boost::parameter::keyword<Tag>&>(instance);
+ }
+ };
+
+ template <typename Tag>
+ ::boost::parameter::keyword<Tag> const ::boost::parameter
+ ::keyword<Tag>::instance = ::boost::parameter::keyword<Tag>();
+}} // namespace boost::parameter
+
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+#if !defined(BOOST_NO_SFINAE)
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_scalar.hpp>
+#include <boost/type_traits/is_const.hpp>
+#endif // BOOST_NO_SFINAE
+
+namespace boost { namespace parameter {
+
+ // Instances of unique specializations of keyword<...> serve to
+ // associate arguments with parameter names. For example:
+ //
+ // struct rate_; // parameter names
+ // struct skew_;
+ //
+ // namespace
+ // {
+ // keyword<rate_> rate; // keywords
+ // keyword<skew_> skew;
+ // }
+ //
+ // ...
+ //
+ // f(rate = 1, skew = 2.4);
+ template <typename Tag>
+ struct keyword
{
- return const_cast<keyword<Tag>&>(instance);
- }
-};
-
-template <class Tag>
-keyword<Tag> const keyword<Tag>::instance = {};
-
-// Reduces boilerplate required to declare and initialize keywords
-// without violating ODR. Declares a keyword tag type with the given
-// name in namespace tag_namespace, and declares and initializes a
-// reference in an anonymous namespace to a singleton instance of that
-// type.
-
-#define BOOST_PARAMETER_KEYWORD(tag_namespace,name) \
- namespace tag_namespace \
- { \
- struct name \
- { \
- static char const* keyword_name() \
- { \
- return #name; \
- } \
- }; \
- } \
- namespace \
- { \
- ::boost::parameter::keyword<tag_namespace::name> const& name \
- = ::boost::parameter::keyword<tag_namespace::name>::instance;\
- }
+ typedef Tag tag;
+
+ inline BOOST_CONSTEXPR keyword()
+ {
+ }
+
+ template <typename T>
+#if defined(BOOST_NO_SFINAE)
+ inline typename ::boost::parameter::aux::tag<Tag,T const&>::type
+#else
+ inline BOOST_CONSTEXPR typename ::boost::lazy_enable_if<
+ typename ::boost::mpl::eval_if<
+ ::boost::is_scalar<T>
+ , ::boost::mpl::true_
+ , ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::in_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >
+ >
+ >::type
+ , ::boost::parameter::aux::tag<Tag,T const&>
+ >::type
+#endif // BOOST_NO_SFINAE
+ operator=(T const& x) const
+ {
+ typedef typename ::boost::parameter::aux
+ ::tag<Tag,T const&>::type result;
+ return result(x);
+ }
+
+ template <typename Default>
+#if defined(BOOST_NO_SFINAE)
+ inline ::boost::parameter::aux::default_<Tag,Default const>
+#else
+ inline BOOST_CONSTEXPR typename ::boost::enable_if<
+ typename ::boost::mpl::eval_if<
+ ::boost::is_scalar<Default>
+ , ::boost::mpl::true_
+ , ::boost::mpl::eval_if<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::in_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >
+ >
+ >::type
+ , ::boost::parameter::aux::default_<Tag,Default const>
+ >::type
+#endif // BOOST_NO_SFINAE
+ operator|(Default const& d) const
+ {
+ return ::boost::parameter::aux::default_<Tag,Default const>(d);
+ }
+
+ template <typename T>
+#if defined(BOOST_NO_SFINAE)
+ inline typename ::boost::parameter::aux::tag<Tag,T&>::type
+#else
+ inline BOOST_CONSTEXPR typename ::boost::lazy_enable_if<
+ typename ::boost::mpl::eval_if<
+ typename ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >::type
+ , ::boost::mpl::if_<
+ ::boost::is_const<T>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::false_
+ >::type
+ , ::boost::parameter::aux::tag<Tag,T&>
+ >::type
+#endif // BOOST_NO_SFINAE
+ operator=(T& x) const
+ {
+ typedef typename ::boost::parameter::aux
+ ::tag<Tag,T&>::type result;
+ return result(x);
+ }
+ template <typename Default>
+#if defined(BOOST_NO_SFINAE)
+ inline ::boost::parameter::aux::default_<Tag,Default>
+#else
+ inline BOOST_CONSTEXPR typename ::boost::enable_if<
+ typename ::boost::mpl::eval_if<
+ typename ::boost::mpl::if_<
+ ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::out_reference
+ >
+ , ::boost::mpl::true_
+ , ::boost::is_same<
+ typename Tag::qualifier
+ , ::boost::parameter::forward_reference
+ >
+ >::type
+ , ::boost::mpl::if_<
+ ::boost::is_const<Default>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::false_
+ >::type
+ , ::boost::parameter::aux::default_<Tag,Default>
+ >::type
+#endif // BOOST_NO_SFINAE
+ operator|(Default& d) const
+ {
+ return ::boost::parameter::aux::default_<Tag,Default>(d);
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR
+ ::boost::parameter::aux::lazy_default<Tag,Default const>
+ operator||(Default const& d) const
+ {
+ return ::boost::parameter::aux
+ ::lazy_default<Tag,Default const>(d);
+ }
+
+ template <typename Default>
+ inline BOOST_CONSTEXPR
+ ::boost::parameter::aux::lazy_default<Tag,Default>
+ operator||(Default& d) const
+ {
+ return ::boost::parameter::aux::lazy_default<Tag,Default>(d);
+ }
+
+ public: // Insurance against ODR violations
+ // Users will need to define their keywords in header files. To
+ // prevent ODR violations, it's important that the keyword used in
+ // every instantiation of a function template is the same object.
+ // We provide a reference to a common instance of each keyword
+ // object and prevent construction by users.
+ static ::boost::parameter::keyword<Tag> const instance;
+
+ // This interface is deprecated.
+ static ::boost::parameter::keyword<Tag>& get()
+ {
+ return const_cast< ::boost::parameter::keyword<Tag>&>(instance);
+ }
+ };
+
+ template <typename Tag>
+ ::boost::parameter::keyword<Tag> const ::boost::parameter
+ ::keyword<Tag>::instance = ::boost::parameter::keyword<Tag>();
}} // namespace boost::parameter
-#endif // KEYWORD_050328_HPP
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+
+#include <boost/parameter/aux_/name.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+// Reduces boilerplate required to declare and initialize keywords without
+// violating ODR. Declares a keyword tag type with the given name in
+// namespace tag_namespace, and declares and initializes a reference in an
+// anonymous namespace to a singleton instance of that type.
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_KEYWORD(tag_namespace, name) \
+ namespace tag_namespace \
+ { \
+ struct name \
+ { \
+ static BOOST_CONSTEXPR char const* keyword_name() \
+ { \
+ return BOOST_PP_STRINGIZE(name); \
+ } \
+ using _ = BOOST_PARAMETER_TAG_PLACEHOLDER_TYPE(name); \
+ using _1 = _; \
+ BOOST_PARAMETER_TAG_MP11_PLACEHOLDER_BINDING(binding_fn, name); \
+ BOOST_PARAMETER_TAG_MP11_PLACEHOLDER_VALUE(fn, name); \
+ using qualifier = ::boost::parameter::forward_reference; \
+ }; \
+ } \
+ namespace \
+ { \
+ ::boost::parameter::keyword<tag_namespace::name> const& name \
+ = ::boost::parameter::keyword<tag_namespace::name>::instance; \
+ }
+/**/
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_KEYWORD(tag_namespace, name) \
+ namespace tag_namespace \
+ { \
+ struct name \
+ { \
+ static BOOST_CONSTEXPR char const* keyword_name() \
+ { \
+ return BOOST_PP_STRINGIZE(name); \
+ } \
+ typedef BOOST_PARAMETER_TAG_PLACEHOLDER_TYPE(name) _; \
+ typedef BOOST_PARAMETER_TAG_PLACEHOLDER_TYPE(name) _1; \
+ typedef ::boost::parameter::forward_reference qualifier; \
+ }; \
+ } \
+ namespace \
+ { \
+ ::boost::parameter::keyword<tag_namespace::name> const& name \
+ = ::boost::parameter::keyword<tag_namespace::name>::instance; \
+ }
+/**/
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+#endif // include guard
diff --git a/boost/parameter/keyword_fwd.hpp b/boost/parameter/keyword_fwd.hpp
new file mode 100644
index 0000000000..d2ba0a78f7
--- /dev/null
+++ b/boost/parameter/keyword_fwd.hpp
@@ -0,0 +1,23 @@
+// Copyright Cromwell D. Enage 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_PARAMETER_KEYWORD_FWD_HPP
+#define BOOST_PARAMETER_KEYWORD_FWD_HPP
+
+namespace boost { namespace parameter {
+
+ struct in_reference;
+ struct out_reference;
+ typedef ::boost::parameter::out_reference in_out_reference;
+ struct forward_reference;
+ struct consume_reference;
+ typedef ::boost::parameter::consume_reference move_from_reference;
+
+ template <typename Tag>
+ struct keyword;
+}} // namespace boost::parameter
+
+#endif // include guard
+
diff --git a/boost/parameter/macros.hpp b/boost/parameter/macros.hpp
index 83fbfb5a60..5ff20fc232 100644
--- a/boost/parameter/macros.hpp
+++ b/boost/parameter/macros.hpp
@@ -1,99 +1,232 @@
-// Copyright David Abrahams, Daniel Wallin 2003. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Copyright Cromwell D. Enage 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_PARAMETER_MACROS_050412_HPP
#define BOOST_PARAMETER_MACROS_050412_HPP
-#include <boost/preprocessor/tuple/elem.hpp>
-#include <boost/preprocessor/repetition/repeat_from_to.hpp>
-#include <boost/preprocessor/arithmetic/inc.hpp>
-#include <boost/preprocessor/logical/bool.hpp>
-#include <boost/preprocessor/punctuation/comma_if.hpp>
-#include <boost/preprocessor/control/expr_if.hpp>
+#include <boost/parameter/config.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
+
+#if !defined(BOOST_NO_SFINAE) && \
+ !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
+
+#define BOOST_PARAMETER_MATCH_TYPE(n, param) \
+ , typename param::match<BOOST_PP_ENUM_PARAMS(n, T)>::type kw = param()
+/**/
+
+#define BOOST_PARAMETER_MATCH_TYPE_Z(z, n, param) \
+ , typename param::match<BOOST_PP_ENUM_PARAMS_Z(z, n, T)>::type kw = param()
+/**/
+
+#else // SFINAE disbled, or Borland workarounds needed.
+
+#define BOOST_PARAMETER_MATCH_TYPE(n, param) , param kw = param()
+/**/
+
+#define BOOST_PARAMETER_MATCH_TYPE_Z(z, n, param) , param kw = param()
+/**/
+
+#endif // SFINAE enabled, not Borland.
+
+#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/cat.hpp>
-#include <boost/detail/workaround.hpp>
-
-#define BOOST_PARAMETER_FUN_TEMPLATE_HEAD1(n) \
- template<BOOST_PP_ENUM_PARAMS(n, class T)>
-
-#define BOOST_PARAMETER_FUN_TEMPLATE_HEAD0(n)
-
-#if ! defined(BOOST_NO_SFINAE) && ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
-
-# define BOOST_PARAMETER_MATCH_TYPE(n, param) \
- BOOST_PP_EXPR_IF(n, typename) param::match \
- < \
- BOOST_PP_ENUM_PARAMS(n, T) \
- >::type
-
-#else
-
-# define BOOST_PARAMETER_MATCH_TYPE(n, param) param
-
-#endif
-
-#define BOOST_PARAMETER_FUN_DECL(z, n, params) \
- \
- BOOST_PP_CAT(BOOST_PARAMETER_FUN_TEMPLATE_HEAD, BOOST_PP_BOOL(n))(n) \
- \
- BOOST_PP_TUPLE_ELEM(3, 0, params) \
- BOOST_PP_TUPLE_ELEM(3, 1, params)( \
- BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& p) \
- BOOST_PP_COMMA_IF(n) \
- BOOST_PARAMETER_MATCH_TYPE(n,BOOST_PP_TUPLE_ELEM(3, 2, params)) \
- kw = BOOST_PP_TUPLE_ELEM(3, 2, params)() \
- ) \
- { \
- return BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 1, params), _with_named_params)( \
- kw(BOOST_PP_ENUM_PARAMS(n, p)) \
- ); \
+
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+#define BOOST_PARAMETER_FUN_0(z, n, params) \
+ BOOST_PP_TUPLE_ELEM(3, 0, params) BOOST_PP_TUPLE_ELEM(3, 1, params)() \
+ { \
+ return BOOST_PP_CAT( \
+ BOOST_PP_TUPLE_ELEM(3, 1, params) \
+ , _with_named_params \
+ )(BOOST_PP_TUPLE_ELEM(3, 2, params)()()); \
+ }
+/**/
+
+#include <utility>
+
+#define BOOST_PARAMETER_FUN_DECL_PARAM(z, n, p) \
+ ::std::forward<BOOST_PP_CAT(T, n)>(BOOST_PP_CAT(p, n))
+/**/
+
+#include <boost/preprocessor/repetition/enum.hpp>
+
+#define BOOST_PARAMETER_FUN_DEFN_1(z, n, params) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename T)> \
+ BOOST_PP_TUPLE_ELEM(3, 0, params) \
+ BOOST_PP_TUPLE_ELEM(3, 1, params)( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, T, && p) \
+ BOOST_PARAMETER_MATCH_TYPE_Z( \
+ z, n, BOOST_PP_TUPLE_ELEM(3, 2, params) \
+ ) \
+ ) \
+ { \
+ return BOOST_PP_CAT( \
+ BOOST_PP_TUPLE_ELEM(3, 1, params) \
+ , _with_named_params \
+ )( \
+ kw( \
+ BOOST_PP_CAT(BOOST_PP_ENUM_, z)( \
+ n, BOOST_PARAMETER_FUN_DECL_PARAM, p \
+ ) \
+ ) \
+ ); \
}
+/**/
+
+#define BOOST_PARAMETER_FUN_DECL(z, n, params) \
+ BOOST_PP_IF( \
+ n \
+ , BOOST_PARAMETER_FUN_DEFN_1 \
+ , BOOST_PARAMETER_FUN_0 \
+ )(z, n, params)
+/**/
+
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+#define BOOST_PARAMETER_FUN_DEFN_0(z, n, params) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename T)> \
+ BOOST_PP_TUPLE_ELEM(3, 0, params) \
+ BOOST_PP_TUPLE_ELEM(3, 1, params)( \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, T, const& p) \
+ BOOST_PARAMETER_MATCH_TYPE_Z( \
+ z, n, BOOST_PP_TUPLE_ELEM(3, 2, params) \
+ ) \
+ ) \
+ { \
+ return BOOST_PP_CAT( \
+ BOOST_PP_TUPLE_ELEM(3, 1, params) \
+ , _with_named_params \
+ )(kw(BOOST_PP_ENUM_PARAMS_Z(z, n, p))); \
+ }
+/**/
+
+#include <boost/preprocessor/seq/seq.hpp>
+
+#define BOOST_PARAMETER_FUN_0(z, n, seq) \
+ BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq))) \
+ BOOST_PP_TUPLE_ELEM(3, 1, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)))() \
+ { \
+ return BOOST_PP_CAT( \
+ BOOST_PP_TUPLE_ELEM( \
+ 3, 1, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq)) \
+ ) \
+ , _with_named_params \
+ )( \
+ BOOST_PP_TUPLE_ELEM(3, 2, BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_TAIL(seq))) \
+ ()() \
+ ); \
+ }
+/**/
+
+#include <boost/parameter/aux_/preprocessor/binary_seq_to_args.hpp>
+#include <boost/preprocessor/seq/size.hpp>
+
+#define BOOST_PARAMETER_FUN_DEFN_R(r, seq) \
+ template < \
+ BOOST_PP_ENUM_PARAMS( \
+ BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_TAIL(seq)) \
+ , typename T \
+ ) \
+ > BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_SEQ_HEAD(seq)) \
+ BOOST_PP_TUPLE_ELEM(3, 1, BOOST_PP_SEQ_HEAD(seq))( \
+ BOOST_PARAMETER_AUX_PP_BINARY_SEQ_TO_ARGS( \
+ BOOST_PP_SEQ_TAIL(seq), (T)(p) \
+ ) \
+ BOOST_PARAMETER_MATCH_TYPE( \
+ BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_TAIL(seq)) \
+ , BOOST_PP_TUPLE_ELEM(3, 2, BOOST_PP_SEQ_HEAD(seq)) \
+ ) \
+ ) \
+ { \
+ return BOOST_PP_CAT( \
+ BOOST_PP_TUPLE_ELEM(3, 1, BOOST_PP_SEQ_HEAD(seq)) \
+ , _with_named_params \
+ )( \
+ kw( \
+ BOOST_PP_ENUM_PARAMS( \
+ BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_TAIL(seq)), p \
+ ) \
+ ) \
+ ); \
+ }
+/**/
+
+#include <boost/parameter/aux_/preprocessor/binary_seq_for_each.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+#define BOOST_PARAMETER_FUN_DEFN_1(z, n, params) \
+ BOOST_PP_IF( \
+ n \
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_Z \
+ , BOOST_PARAMETER_FUN_0 \
+ )(z, n, (BOOST_PARAMETER_FUN_DEFN_R)(params))
+/**/
+
+#include <boost/preprocessor/comparison/less.hpp>
+
+#define BOOST_PARAMETER_FUN_DECL(z, n, params) \
+ BOOST_PP_CAT( \
+ BOOST_PARAMETER_FUN_DEFN_ \
+ , BOOST_PP_LESS( \
+ n \
+ , BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY \
+ ) \
+ )(z, n, params)
+/**/
+
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
// Generates:
//
-// template<class Params>
+// template <typename Params>
// ret name ## _with_named_params(Params const&);
//
-// template<class T0>
-// ret name(T0 const& p0, typename parameters::match<T0>::type kw = parameters())
+// template <typename T0>
+// ret name(
+// T0 && p0
+// , typename parameters::match<T0>::type kw = parameters()
+// )
// {
// return name ## _with_named_params(kw(p0));
// }
//
-// template<class T0, ..., class TN>
-// ret name(T0 const& p0, ..., TN const& PN
-// , typename parameters::match<T0, ..., TN>::type kw = parameters())
+// template <typename T0, ..., typename T ## N>
+// ret name(
+// T0 && p0, ..., TN && p ## N
+// , typename parameters::match<T0, ..., T ## N>::type kw = parameters()
+// )
// {
-// return name ## _with_named_params(kw(p0, ..., pN));
+// return name ## _with_named_params(kw(p0, ..., p ## N));
// }
//
-// template<class Params>
+// template <typename Params>
// ret name ## _with_named_params(Params const&)
//
-// lo and hi determines the min and max arity of the generated functions.
-
-#define BOOST_PARAMETER_FUN(ret, name, lo, hi, parameters) \
- \
- template<class Params> \
- ret BOOST_PP_CAT(name, _with_named_params)(Params const& p); \
- \
- BOOST_PP_REPEAT_FROM_TO( \
- lo, BOOST_PP_INC(hi), BOOST_PARAMETER_FUN_DECL, (ret, name, parameters)) \
- \
- template<class Params> \
- ret BOOST_PP_CAT(name, _with_named_params)(Params const& p)
+// lo and hi determine the min and max arities of the generated functions.
-#define BOOST_PARAMETER_MEMFUN(ret, name, lo, hi, parameters) \
- \
- BOOST_PP_REPEAT_FROM_TO( \
- lo, BOOST_PP_INC(hi), BOOST_PARAMETER_FUN_DECL, (ret, name, parameters)) \
- \
- template<class Params> \
+#define BOOST_PARAMETER_MEMFUN(ret, name, lo, hi, parameters) \
+ BOOST_PP_REPEAT_FROM_TO( \
+ lo, BOOST_PP_INC(hi), BOOST_PARAMETER_FUN_DECL \
+ , (ret, name, parameters) \
+ ) \
+ template <typename Params> \
ret BOOST_PP_CAT(name, _with_named_params)(Params const& p)
+/**/
+
+#define BOOST_PARAMETER_FUN(ret, name, lo, hi, parameters) \
+ template <typename Params> \
+ ret BOOST_PP_CAT(name, _with_named_params)(Params const& p); \
+ BOOST_PARAMETER_MEMFUN(ret, name, lo, hi, parameters)
+/**/
-#endif // BOOST_PARAMETER_MACROS_050412_HPP
+#endif // include guard
diff --git a/boost/parameter/match.hpp b/boost/parameter/match.hpp
index 2fa3f1750a..edb59f96a5 100644
--- a/boost/parameter/match.hpp
+++ b/boost/parameter/match.hpp
@@ -1,42 +1,34 @@
-// Copyright David Abrahams 2005. Distributed under the Boost
-// Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_PARAMETER_MATCH_DWA2005714_HPP
-# define BOOST_PARAMETER_MATCH_DWA2005714_HPP
-
-# include <boost/detail/workaround.hpp>
-# include <boost/preprocessor/seq/enum.hpp>
-
-# if BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
-// Temporary version of BOOST_PP_SEQ_ENUM until Paul M. integrates the workaround.
-# define BOOST_PARAMETER_SEQ_ENUM_I(size,seq) BOOST_PP_CAT(BOOST_PP_SEQ_ENUM_, size) seq
-# define BOOST_PARAMETER_SEQ_ENUM(seq) BOOST_PARAMETER_SEQ_ENUM_I(BOOST_PP_SEQ_SIZE(seq), seq)
-# else
-# define BOOST_PARAMETER_SEQ_ENUM(seq) BOOST_PP_SEQ_ENUM(seq)
-# endif
-
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-
-# include <boost/parameter/config.hpp>
-# include <boost/parameter/aux_/void.hpp>
-# include <boost/preprocessor/arithmetic/sub.hpp>
-# include <boost/preprocessor/facilities/intercept.hpp>
-# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+// Copyright David Abrahams 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
-# define BOOST_PARAMETER_MATCH_DEFAULTS(ArgTypes) \
- BOOST_PP_ENUM_TRAILING_PARAMS( \
- BOOST_PP_SUB( \
- BOOST_PARAMETER_MAX_ARITY \
- , BOOST_PP_SEQ_SIZE(ArgTypes) \
- ) \
- , ::boost::parameter::void_ BOOST_PP_INTERCEPT \
- )
-
-# else
-
-# define BOOST_PARAMETER_MATCH_DEFAULTS(ArgTypes)
-
-# endif
+#ifndef BOOST_PARAMETER_MATCH_DWA2005714_HPP
+#define BOOST_PARAMETER_MATCH_DWA2005714_HPP
+
+#include <boost/parameter/config.hpp>
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/facilities/intercept.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+#include <boost/preprocessor/seq/size.hpp>
+
+#define BOOST_PARAMETER_MATCH_DEFAULTS(ArgTypes) \
+ BOOST_PP_ENUM_TRAILING_PARAMS( \
+ BOOST_PP_SUB( \
+ BOOST_PARAMETER_MAX_ARITY \
+ , BOOST_PP_SEQ_SIZE(ArgTypes) \
+ ) \
+ , ::boost::parameter::void_ BOOST_PP_INTERCEPT \
+ )
+/**/
+#else
+#define BOOST_PARAMETER_MATCH_DEFAULTS(ArgTypes)
+#endif
+
+#include <boost/parameter/aux_/preprocessor/seq_enum.hpp>
//
// Generates, e.g.
@@ -45,11 +37,12 @@
//
// with workarounds for Borland compatibility.
//
+#define BOOST_PARAMETER_MATCH(ParameterSpec, ArgTypes, name) \
+ typename ParameterSpec::match< \
+ BOOST_PARAMETER_SEQ_ENUM(ArgTypes) \
+ BOOST_PARAMETER_MATCH_DEFAULTS(ArgTypes) \
+ >::type name = ParameterSpec()
+/**/
-# define BOOST_PARAMETER_MATCH(ParameterSpec, ArgTypes, name) \
- typename ParameterSpec ::match< \
- BOOST_PARAMETER_SEQ_ENUM(ArgTypes) \
- BOOST_PARAMETER_MATCH_DEFAULTS(ArgTypes) \
- >::type name = ParameterSpec ()
+#endif // include guard
-#endif // BOOST_PARAMETER_MATCH_DWA2005714_HPP
diff --git a/boost/parameter/name.hpp b/boost/parameter/name.hpp
index f439df416b..3b63fc3e33 100644
--- a/boost/parameter/name.hpp
+++ b/boost/parameter/name.hpp
@@ -1,146 +1,120 @@
-// Copyright Daniel Wallin 2006. Use, modification and distribution is
-// subject to the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright Daniel Wallin 2006.
+// Copyright Cromwell D. Enage 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_PARAMETER_NAME_060806_HPP
-# define BOOST_PARAMETER_NAME_060806_HPP
-
-# include <boost/parameter/keyword.hpp>
-# include <boost/parameter/value_type.hpp>
-# include <boost/detail/workaround.hpp>
-# include <boost/preprocessor/cat.hpp>
-# include <boost/preprocessor/stringize.hpp>
-# include <boost/preprocessor/control/iif.hpp>
-# include <boost/preprocessor/tuple/eat.hpp>
-# include <boost/preprocessor/tuple/elem.hpp>
-# include <boost/mpl/placeholders.hpp>
-
-# if !defined(BOOST_NO_SFINAE) \
- && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
-
-# include <boost/utility/enable_if.hpp>
-# include <boost/mpl/lambda.hpp>
-
-namespace boost { namespace parameter { namespace aux {
-
-// Tag type passed to MPL lambda.
-struct lambda_tag;
-
-struct name_tag_base
-{};
-
-template <class Tag>
-struct name_tag
-{};
-
-template <class T>
-struct is_name_tag
- : mpl::false_
-{};
-
-}}} // namespace boost::parameter::aux
-
-namespace boost { namespace mpl {
-
-template <class T>
-struct lambda<
- T
- , typename boost::enable_if<
- parameter::aux::is_name_tag<T>, parameter::aux::lambda_tag
- >::type
->
-{
- typedef true_ is_le;
- typedef bind3< quote3<parameter::value_type>, arg<2>, T, void> result_;
- typedef result_ type;
-};
-
-}} // namespace boost::mpl
-
-# endif
-
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-# include <boost/preprocessor/detail/split.hpp>
-// From Paul Mensonides
-# define BOOST_PARAMETER_IS_BINARY(x) \
- BOOST_PP_SPLIT(1, BOOST_PARAMETER_IS_BINARY_C x BOOST_PP_COMMA() 0) \
- /**/
-# define BOOST_PARAMETER_IS_BINARY_C(x,y) \
- ~, 1 BOOST_PP_RPAREN() \
- BOOST_PP_TUPLE_EAT(2) BOOST_PP_LPAREN() ~ \
- /**/
-# else
-# include <boost/preprocessor/detail/is_binary.hpp>
-# define BOOST_PARAMETER_IS_BINARY(x) BOOST_PP_IS_BINARY(x)
-# endif
-
-# define BOOST_PARAMETER_BASIC_NAME(tag_namespace, tag, name) \
- namespace tag_namespace \
- { \
- struct tag \
- { \
- static char const* keyword_name() \
- { \
- return BOOST_PP_STRINGIZE(tag); \
- } \
- \
- typedef boost::parameter::value_type< \
- boost::mpl::_2, tag, boost::parameter::void_ \
- > _; \
- \
- typedef boost::parameter::value_type< \
- boost::mpl::_2, tag, boost::parameter::void_ \
- > _1; \
- }; \
- } \
- namespace \
- { \
- ::boost::parameter::keyword<tag_namespace::tag> const& name \
- = ::boost::parameter::keyword<tag_namespace::tag>::instance; \
+#define BOOST_PARAMETER_NAME_060806_HPP
+
+#include <boost/parameter/aux_/name.hpp>
+#include <boost/preprocessor/stringize.hpp>
+#include <boost/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_NAME_TAG(tag_namespace, tag, q) \
+ namespace tag_namespace \
+ { \
+ struct tag \
+ { \
+ static BOOST_CONSTEXPR char const* keyword_name() \
+ { \
+ return BOOST_PP_STRINGIZE(tag); \
+ } \
+ using _ = BOOST_PARAMETER_TAG_PLACEHOLDER_TYPE(tag); \
+ using _1 = _; \
+ BOOST_PARAMETER_TAG_MP11_PLACEHOLDER_BINDING(binding_fn, tag); \
+ BOOST_PARAMETER_TAG_MP11_PLACEHOLDER_VALUE(fn, tag); \
+ using qualifier = ::boost::parameter::q; \
+ }; \
}
+/**/
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_NAME_TAG(tag_namespace, tag, q) \
+ namespace tag_namespace \
+ { \
+ struct tag \
+ { \
+ static BOOST_CONSTEXPR char const* keyword_name() \
+ { \
+ return BOOST_PP_STRINGIZE(tag); \
+ } \
+ typedef BOOST_PARAMETER_TAG_PLACEHOLDER_TYPE(tag) _; \
+ typedef BOOST_PARAMETER_TAG_PLACEHOLDER_TYPE(tag) _1; \
+ typedef ::boost::parameter::q qualifier; \
+ }; \
+ }
+/**/
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+#include <boost/parameter/keyword.hpp>
+
+#define BOOST_PARAMETER_NAME_KEYWORD(tag_namespace, tag, name) \
+ namespace \
+ { \
+ ::boost::parameter::keyword<tag_namespace::tag> const& name \
+ = ::boost::parameter::keyword<tag_namespace::tag>::instance; \
+ }
+/**/
+
+#define BOOST_PARAMETER_BASIC_NAME(tag_namespace, tag, qualifier, name) \
+ BOOST_PARAMETER_NAME_TAG(tag_namespace, tag, qualifier) \
+ BOOST_PARAMETER_NAME_KEYWORD(tag_namespace, tag, name)
+/**/
+
+#define BOOST_PARAMETER_COMPLEX_NAME_TUPLE1(object, namespace) \
+ (object, namespace), ~
+/**/
-# define BOOST_PARAMETER_COMPLEX_NAME_TUPLE1(tag,namespace) \
- (tag, namespace), ~
+#include <boost/preprocessor/tuple/elem.hpp>
-# define BOOST_PARAMETER_COMPLEX_NAME_TUPLE(name) \
+#define BOOST_PARAMETER_COMPLEX_NAME_TUPLE(name) \
BOOST_PP_TUPLE_ELEM(2, 0, (BOOST_PARAMETER_COMPLEX_NAME_TUPLE1 name))
+/**/
-# define BOOST_PARAMETER_COMPLEX_NAME_TAG(name) \
+#define BOOST_PARAMETER_COMPLEX_NAME_OBJECT(name) \
BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PARAMETER_COMPLEX_NAME_TUPLE(name))
+/**/
-# define BOOST_PARAMETER_COMPLEX_NAME_NAMESPACE(name) \
+#define BOOST_PARAMETER_COMPLEX_NAME_NAMESPACE(name) \
BOOST_PP_TUPLE_ELEM(2, 1, BOOST_PARAMETER_COMPLEX_NAME_TUPLE(name))
+/**/
-# define BOOST_PARAMETER_COMPLEX_NAME(name) \
- BOOST_PARAMETER_BASIC_NAME( \
- BOOST_PARAMETER_COMPLEX_NAME_NAMESPACE(name) \
- , BOOST_PP_TUPLE_EAT(2) name \
- , BOOST_PARAMETER_COMPLEX_NAME_TAG(name) \
- ) \
+#include <boost/parameter/aux_/preprocessor/qualifier.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+#define BOOST_PARAMETER_COMPLEX_NAME(name) \
+ BOOST_PARAMETER_BASIC_NAME( \
+ BOOST_PARAMETER_COMPLEX_NAME_NAMESPACE(name) \
+ , BOOST_PARAMETER_UNQUALIFIED(BOOST_PP_TUPLE_EAT(2) name) \
+ , BOOST_PARAMETER_GET_QUALIFIER(BOOST_PP_TUPLE_EAT(2) name) \
+ , BOOST_PARAMETER_COMPLEX_NAME_OBJECT(name) \
+ )
/**/
-# define BOOST_PARAMETER_SIMPLE_NAME(name) \
- BOOST_PARAMETER_BASIC_NAME(tag, name, BOOST_PP_CAT(_, name))
+#include <boost/preprocessor/cat.hpp>
-# define BOOST_PARAMETER_NAME(name) \
- BOOST_PP_IIF( \
- BOOST_PARAMETER_IS_BINARY(name) \
- , BOOST_PARAMETER_COMPLEX_NAME \
- , BOOST_PARAMETER_SIMPLE_NAME \
- )(name) \
+#define BOOST_PARAMETER_SIMPLE_NAME(name) \
+ BOOST_PARAMETER_BASIC_NAME( \
+ tag \
+ , BOOST_PARAMETER_UNQUALIFIED(name) \
+ , BOOST_PARAMETER_GET_QUALIFIER(name) \
+ , BOOST_PP_CAT(_, BOOST_PARAMETER_UNQUALIFIED(name)) \
+ )
/**/
+#include <boost/parameter/aux_/preprocessor/is_binary.hpp>
+#include <boost/preprocessor/control/iif.hpp>
-# define BOOST_PARAMETER_TEMPLATE_KEYWORD(name) \
- namespace tag \
- { \
- struct name; \
- } \
- template <class T> \
- struct name \
- : boost::parameter::template_keyword<tag::name, T> \
- {}; \
+#define BOOST_PARAMETER_NAME(name) \
+ BOOST_PP_IIF( \
+ BOOST_PARAMETER_IS_BINARY(name) \
+ , BOOST_PARAMETER_COMPLEX_NAME \
+ , BOOST_PARAMETER_SIMPLE_NAME \
+ )(name)
/**/
-#endif // BOOST_PARAMETER_NAME_060806_HPP
+#include <boost/parameter/template_keyword.hpp>
+
+#endif // include guard
diff --git a/boost/parameter/nested_keyword.hpp b/boost/parameter/nested_keyword.hpp
new file mode 100644
index 0000000000..fc180ecf21
--- /dev/null
+++ b/boost/parameter/nested_keyword.hpp
@@ -0,0 +1,111 @@
+// Copyright Eric Niebler 2005.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_NESTED_KEYWORD_HPP
+#define BOOST_PARAMETER_NESTED_KEYWORD_HPP
+
+#include <boost/parameter/aux_/name.hpp>
+#include <boost/parameter/keyword.hpp>
+#include <boost/parameter/config.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_NESTED_KEYWORD_AUX(tag_namespace, q, name, alias) \
+ namespace tag_namespace \
+ { \
+ template <int Dummy = 0> \
+ struct BOOST_PP_CAT(name, _) \
+ { \
+ static BOOST_CONSTEXPR char const* keyword_name() \
+ { \
+ return BOOST_PP_STRINGIZE(name); \
+ } \
+ using _ = BOOST_PARAMETER_TAG_PLACEHOLDER_TYPE( \
+ BOOST_PP_CAT(name, _)<Dummy> \
+ ); \
+ using _1 = BOOST_PARAMETER_TAG_PLACEHOLDER_TYPE( \
+ BOOST_PP_CAT(name, _)<Dummy> \
+ ); \
+ BOOST_PARAMETER_TAG_MP11_PLACEHOLDER_BINDING( \
+ binding_fn \
+ , BOOST_PP_CAT(name, _)<Dummy> \
+ ); \
+ BOOST_PARAMETER_TAG_MP11_PLACEHOLDER_VALUE( \
+ fn \
+ , BOOST_PP_CAT(name, _)<Dummy> \
+ ); \
+ using qualifier = ::boost::parameter::q; \
+ static ::boost::parameter::keyword< \
+ BOOST_PP_CAT(name, _)<Dummy> \
+ > const& alias; \
+ }; \
+ template <int Dummy> \
+ ::boost::parameter::keyword< \
+ BOOST_PP_CAT(name, _)<Dummy> \
+ > const& BOOST_PP_CAT(name, _)<Dummy>::alias \
+ = ::boost::parameter::keyword< \
+ BOOST_PP_CAT(name, _)<Dummy> \
+ >::instance; \
+ typedef BOOST_PP_CAT(name, _)<> name; \
+ } \
+ namespace \
+ { \
+ ::boost::parameter::keyword<tag_namespace::name> const& name \
+ = ::boost::parameter::keyword<tag_namespace::name>::instance; \
+ }
+/**/
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_NESTED_KEYWORD_AUX(tag_namespace, q, name, alias) \
+ namespace tag_namespace \
+ { \
+ template <int Dummy = 0> \
+ struct BOOST_PP_CAT(name, _) \
+ { \
+ static BOOST_CONSTEXPR char const* keyword_name() \
+ { \
+ return BOOST_PP_STRINGIZE(name); \
+ } \
+ typedef BOOST_PARAMETER_TAG_PLACEHOLDER_TYPE( \
+ BOOST_PP_CAT(name, _)<Dummy> \
+ ) _; \
+ typedef BOOST_PARAMETER_TAG_PLACEHOLDER_TYPE( \
+ BOOST_PP_CAT(name, _)<Dummy> \
+ ) _1; \
+ typedef ::boost::parameter::q qualifier; \
+ static ::boost::parameter::keyword< \
+ BOOST_PP_CAT(name, _)<Dummy> \
+ > const& alias; \
+ }; \
+ template <int Dummy> \
+ ::boost::parameter::keyword< \
+ BOOST_PP_CAT(name, _)<Dummy> \
+ > const& BOOST_PP_CAT(name, _)<Dummy>::alias \
+ = ::boost::parameter::keyword< \
+ BOOST_PP_CAT(name, _)<Dummy> \
+ >::instance; \
+ typedef BOOST_PP_CAT(name, _)<> name; \
+ } \
+ namespace \
+ { \
+ ::boost::parameter::keyword<tag_namespace::name> const& name \
+ = ::boost::parameter::keyword<tag_namespace::name>::instance; \
+ }
+/**/
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+
+#include <boost/parameter/aux_/preprocessor/qualifier.hpp>
+
+#define BOOST_PARAMETER_NESTED_KEYWORD(tag_namespace, name, alias) \
+ BOOST_PARAMETER_NESTED_KEYWORD_AUX( \
+ tag_namespace \
+ , BOOST_PARAMETER_GET_QUALIFIER(name) \
+ , BOOST_PARAMETER_UNQUALIFIED(name) \
+ , alias \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/optional.hpp b/boost/parameter/optional.hpp
new file mode 100644
index 0000000000..c0f94d1007
--- /dev/null
+++ b/boost/parameter/optional.hpp
@@ -0,0 +1,67 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_OPTIONAL_HPP
+#define BOOST_PARAMETER_OPTIONAL_HPP
+
+#include <boost/parameter/aux_/use_default.hpp>
+
+namespace boost { namespace parameter {
+
+ // This metafunction can be used to describe the treatment of particular
+ // named parameters for the purposes of overload elimination with SFINAE,
+ // by placing specializations in the parameters<...> list. In order for
+ // a treated function to participate in overload resolution:
+ //
+ // - The actual argument type matched by every keyword tag
+ // associated with a predicate must satisfy that predicate
+ //
+ // - If a keyword k is specified without an optional<...> or
+ // required<...> wrapper, it is treated as though
+ // optional<k> were specified.
+ template <
+ typename Tag
+ , typename Predicate = ::boost::parameter::aux::use_default
+ >
+ struct optional
+ {
+ typedef Tag key_type;
+ typedef Predicate predicate;
+ };
+}}
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#else
+#include <boost/mpl/bool.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ struct is_optional
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_false
+#else
+ : ::boost::mpl::false_
+#endif
+ {
+ };
+
+ template <typename Tag, typename Predicate>
+ struct is_optional< ::boost::parameter::optional<Tag,Predicate> >
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_true
+#else
+ : ::boost::mpl::true_
+#endif
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/parameters.hpp b/boost/parameter/parameters.hpp
index 97e102434e..e3d62b21cd 100644
--- a/boost/parameter/parameters.hpp
+++ b/boost/parameter/parameters.hpp
@@ -1,931 +1,600 @@
-// Copyright David Abrahams, Daniel Wallin 2003. Use, modification and
-// distribution is subject to the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Copyright Cromwell D. Enage 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_PARAMETERS_031014_HPP
#define BOOST_PARAMETERS_031014_HPP
-#include <boost/detail/is_xxx.hpp>
+#include <boost/parameter/config.hpp>
-#include <boost/type_traits/is_const.hpp>
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
-#include <boost/mpl/lambda.hpp>
-#include <boost/mpl/apply.hpp>
-#include <boost/mpl/always.hpp>
-#include <boost/mpl/and.hpp>
-#include <boost/mpl/or.hpp>
-#include <boost/mpl/if.hpp>
-#include <boost/mpl/identity.hpp>
-#include <boost/mpl/not.hpp>
-#include <boost/mpl/eval_if.hpp>
-#include <boost/mpl/pair.hpp>
+namespace boost { namespace parameter { namespace aux {
+
+ // The make_arg_list<> metafunction produces a reversed arg_list,
+ // so pass the arguments to the arg_list constructor reversed in turn.
+ template <typename ArgList, typename ...Args>
+ struct arg_list_factory;
+}}} // namespace boost::parameter::aux
+#include <boost/parameter/aux_/arg_list.hpp>
+#include <utility>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#else
+#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_same.hpp>
-#include <boost/type_traits/remove_reference.hpp>
+#endif
-#include <boost/preprocessor/repetition/enum.hpp>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
-#include <boost/preprocessor/arithmetic/sub.hpp>
-#include <boost/preprocessor/repetition/repeat.hpp>
-#include <boost/preprocessor/repetition/enum_shifted.hpp>
-#include <boost/preprocessor/repetition/enum_binary_params.hpp>
-#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
-#include <boost/preprocessor/seq/elem.hpp>
-#include <boost/preprocessor/iteration/iterate.hpp>
-#include <boost/preprocessor/facilities/intercept.hpp>
-#include <boost/preprocessor/cat.hpp>
+namespace boost { namespace parameter { namespace aux {
+
+ // TODO: Reduce template code bloat. -- Cromwell D. Enage
+ template <typename ArgList>
+ struct arg_list_factory<ArgList>
+ {
+ template <typename ...ReversedArgs>
+ static inline BOOST_CONSTEXPR ArgList
+ reverse(ReversedArgs&&... reversed_args)
+ {
+ return ArgList(
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ ::boost::mp11::mp_if<
+ ::std::is_same<
+#else
+ typename ::boost::mpl::if_<
+ ::boost::is_same<
+#endif
+ typename ArgList::tagged_arg::value_type
+ , ::boost::parameter::void_
+ >
+ , ::boost::parameter::aux::value_type_is_void
+ , ::boost::parameter::aux::value_type_is_not_void
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ >()
+#else
+ >::type()
+#endif
+ , ::std::forward<ReversedArgs>(reversed_args)...
+ );
+ }
+ };
+
+ template <typename ArgList, typename A0, typename ...Args>
+ struct arg_list_factory<ArgList,A0,Args...>
+ {
+ template <typename ...ReversedArgs>
+ static inline BOOST_CONSTEXPR ArgList
+ reverse(A0&& a0, Args&&... args, ReversedArgs&&... reversed_args)
+ {
+ return ::boost::parameter::aux
+ ::arg_list_factory<ArgList,Args...>::reverse(
+ ::std::forward<Args>(args)...
+ , ::std::forward<A0>(a0)
+ , ::std::forward<ReversedArgs>(reversed_args)...
+ );
+ }
+ };
+}}} // namespace boost::parameter::aux
-#include <boost/parameter/aux_/arg_list.hpp>
-#include <boost/parameter/aux_/yesno.hpp>
#include <boost/parameter/aux_/void.hpp>
-#include <boost/parameter/aux_/default.hpp>
-#include <boost/parameter/aux_/unwrap_cv_reference.hpp>
-#include <boost/parameter/aux_/tagged_argument.hpp>
-#include <boost/parameter/aux_/tag.hpp>
-#include <boost/parameter/aux_/template_keyword.hpp>
-#include <boost/parameter/aux_/set.hpp>
-#include <boost/parameter/config.hpp>
+#include <boost/parameter/aux_/pack/make_arg_list.hpp>
+#include <boost/parameter/aux_/pack/make_parameter_spec_items.hpp>
+#include <boost/parameter/aux_/pack/tag_keyword_arg.hpp>
+#include <boost/parameter/aux_/pack/tag_template_keyword_arg.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/list.hpp>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/pair.hpp>
+#include <boost/mpl/identity.hpp>
+#endif
-namespace parameter_
-{
- template <class T>
- struct unmatched_argument
- {
- BOOST_MPL_ASSERT((boost::is_same<T,void>));
- typedef int type;
- };
-} // namespace parameter_
-
-namespace boost {
-
-template<class T> class reference_wrapper;
-
-namespace parameter {
-
-namespace aux { struct use_default {}; }
-
-// These templates can be used to describe the treatment of particular
-// named parameters for the purposes of overload elimination with
-// SFINAE, by placing specializations in the parameters<...> list. In
-// order for a treated function to participate in overload resolution:
-//
-// - all keyword tags wrapped in required<...> must have a matching
-// actual argument
-//
-// - The actual argument type matched by every keyword tag
-// associated with a predicate must satisfy that predicate
-//
-// If a keyword k is specified without an optional<...> or
-// required<...>, wrapper, it is treated as though optional<k> were
-// specified.
-//
-// If a keyword k is specified with deduced<...>, that keyword
-// will be automatically deduced from the argument list.
-//
-template <class Tag, class Predicate = aux::use_default>
-struct required
-{
- typedef Tag key_type;
- typedef Predicate predicate;
-};
-
-template <class Tag, class Predicate = aux::use_default>
-struct optional
-{
- typedef Tag key_type;
- typedef Predicate predicate;
-};
-
-template <class Tag>
-struct deduced
-{
- typedef Tag key_type;
-};
-
-namespace aux
-{
- // Defines metafunctions, is_required and is_optional, that
- // identify required<...>, optional<...> and deduced<...> specializations.
- BOOST_DETAIL_IS_XXX_DEF(required, required, 2)
- BOOST_DETAIL_IS_XXX_DEF(optional, optional, 2)
- BOOST_DETAIL_IS_XXX_DEF(deduced_aux, deduced, 1)
-
- template <class S>
- struct is_deduced0
- : is_deduced_aux<
- typename S::key_type
- >::type
- {};
-
- template <class S>
- struct is_deduced
- : mpl::eval_if<
- mpl::or_<
- is_optional<S>, is_required<S>
- >
- , is_deduced0<S>
- , mpl::false_
- >::type
- {};
-
- //
- // key_type, has_default, and predicate --
- //
- // These metafunctions accept a ParameterSpec and extract the
- // keyword tag, whether or not a default is supplied for the
- // parameter, and the predicate that the corresponding actual
- // argument type is required match.
- //
- // a ParameterSpec is a specialization of either keyword<...>,
- // required<...>, optional<...>
- //
-
- // helper for key_type<...>, below.
- template <class T>
- struct get_tag_type0
- {
- typedef typename T::key_type type;
- };
-
- template <class T>
- struct get_tag_type
- : mpl::eval_if<
- is_deduced_aux<typename T::key_type>
- , get_tag_type0<typename T::key_type>
- , mpl::identity<typename T::key_type>
- >
- {};
-
- template <class T>
- struct tag_type
- : mpl::eval_if<
- mpl::or_<
- is_optional<T>
- , is_required<T>
- >
- , get_tag_type<T>
- , mpl::identity<T>
- >
- {};
-
- template <class T>
- struct has_default
- : mpl::not_<is_required<T> >
- {};
-
- // helper for get_predicate<...>, below
- template <class T>
- struct get_predicate_or_default
- {
- typedef T type;
- };
-
- template <>
- struct get_predicate_or_default<use_default>
- {
- typedef mpl::always<mpl::true_> type;
- };
-
- // helper for predicate<...>, below
- template <class T>
- struct get_predicate
- {
- typedef typename
- get_predicate_or_default<typename T::predicate>::type
- type;
- };
-
- template <class T>
- struct predicate
- : mpl::eval_if<
- mpl::or_<
- is_optional<T>
- , is_required<T>
- >
- , get_predicate<T>
- , mpl::identity<mpl::always<mpl::true_> >
- >
- {
- };
-
-
- // Converts a ParameterSpec into a specialization of
- // parameter_requirements. We need to do this in order to get the
- // tag_type into the type in a way that can be conveniently matched
- // by a satisfies(...) member function in arg_list.
- template <class ParameterSpec>
- struct as_parameter_requirements
- {
- typedef parameter_requirements<
- typename tag_type<ParameterSpec>::type
- , typename predicate<ParameterSpec>::type
- , typename has_default<ParameterSpec>::type
- > type;
- };
-
- template <class T>
- struct is_named_argument
- : mpl::or_<
- is_template_keyword<T>
- , is_tagged_argument<T>
- >
- {};
-
- // Returns mpl::true_ iff the given ParameterRequirements are
- // satisfied by ArgList.
- template <class ArgList, class ParameterRequirements>
- struct satisfies
- {
-#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
- // VC7.1 can't handle the sizeof() implementation below,
- // so we use this instead.
- typedef typename mpl::apply_wrap3<
- typename ArgList::binding
- , typename ParameterRequirements::keyword
- , void_
- , mpl::false_
- >::type bound;
-
- typedef typename mpl::eval_if<
- is_same<bound, void_>
- , typename ParameterRequirements::has_default
- , mpl::apply_wrap2<
- typename mpl::lambda<
- typename ParameterRequirements::predicate, lambda_tag
- >::type
- , bound
- , ArgList
- >
- >::type type;
+#if !defined(BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE)
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+//#include <boost/mp11/mpl.hpp>
+#define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::mp11::mp_list
+#else
+#include <boost/fusion/container/list/list_fwd.hpp>
+
+// Newer versions of MSVC fail on the evaluate_category and
+// preprocessor_eval_category test programs when parameters uses
+// boost::fusion::list.
+// -- Cromwell D. Enage
+#if defined(BOOST_FUSION_HAS_VARIADIC_LIST) && ( \
+ !defined(BOOST_MSVC) || (BOOST_MSVC < 1800) \
+ )
+#include <boost/fusion/container/list.hpp>
+#include <boost/fusion/mpl.hpp>
+#define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::fusion::list
#else
- BOOST_STATIC_CONSTANT(
- bool, value = (
- sizeof(
- aux::to_yesno(
- ArgList::satisfies((ParameterRequirements*)0, (ArgList*)0)
- )
- ) == sizeof(yes_tag)
- )
- );
-
- typedef mpl::bool_<satisfies::value> type;
+#include <boost/fusion/container/deque/deque_fwd.hpp>
+
+#if defined(BOOST_FUSION_HAS_VARIADIC_DEQUE)
+#include <boost/fusion/container/deque.hpp>
+#include <boost/fusion/mpl.hpp>
+#define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::fusion::deque
+#else
+#include <boost/mpl/vector.hpp>
+#define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::mpl::vector
+#endif // BOOST_FUSION_HAS_VARIADIC_DEQUE
+#endif // BOOST_FUSION_HAS_VARIADIC_LIST
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+#endif // BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE
+
+namespace boost { namespace parameter {
+
+ template <typename ...Spec>
+ struct parameters
+ {
+ typedef BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE<Spec...> parameter_spec;
+
+ typedef typename ::boost::parameter::aux
+ ::make_deduced_list<parameter_spec>::type deduced_list;
+
+ // If the elements of NamedList match the criteria of overload
+ // resolution, returns a type which can be constructed from
+ // parameters. Otherwise, this is not a valid metafunction
+ // (no nested ::type).
+ template <typename ArgumentPackAndError>
+ struct match_base
+#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mpl::if_<
+ typename ::boost::parameter::aux::match_parameters_base_cond<
+ ArgumentPackAndError
+ , parameter_spec
+ >::type
+ , ::boost::mpl::identity<
+ ::boost::parameter::parameters<Spec...>
+ >
+ , ::boost::parameter::void_
+ >
#endif
- };
-
- // Returns mpl::true_ if the requirements of the given ParameterSpec
- // are satisfied by ArgList.
- template <class ArgList, class ParameterSpec>
- struct satisfies_requirements_of
- : satisfies<
- ArgList
- , typename as_parameter_requirements<ParameterSpec>::type
- >
- {};
-
- // Tags a deduced argument Arg with the keyword tag of Spec using TagFn.
- // Returns the tagged argument and the mpl::set<> UsedArgs with the
- // tag of Spec inserted.
- template <class UsedArgs, class Spec, class Arg, class TagFn>
- struct tag_deduced
- {
- typedef mpl::pair<
- typename mpl::apply_wrap2<TagFn, typename tag_type<Spec>::type, Arg>::type
- , typename aux::insert_<UsedArgs, typename tag_type<Spec>::type>::type
- > type;
- };
-
- template <
- class Argument
- , class ArgumentPack
- , class DeducedArgs
- , class UsedArgs
- , class TagFn
- >
- struct deduce_tag;
-
- // Tag type passed to MPL lambda.
- struct lambda_tag;
-
- // Helper for deduce_tag<> below.
- template <
- class Argument
- , class ArgumentPack
- , class DeducedArgs
- , class UsedArgs
- , class TagFn
- >
- struct deduce_tag0
- {
- typedef typename DeducedArgs::spec spec;
-
- typedef typename mpl::apply_wrap2<
- typename mpl::lambda<
- typename spec::predicate, lambda_tag
- >::type
- , Argument
- , ArgumentPack
- >::type condition;
-
- // Deduced parameter matches several arguments.
-
- BOOST_MPL_ASSERT((
- mpl::not_<mpl::and_<
- condition
- , aux::has_key_<UsedArgs, typename tag_type<spec>::type>
- > >
- ));
-
- typedef typename mpl::eval_if<
- condition
- , tag_deduced<UsedArgs, spec, Argument, TagFn>
- , deduce_tag<Argument, ArgumentPack, typename DeducedArgs::tail, UsedArgs, TagFn>
- >::type type;
- };
-
- // Tries to deduced a keyword tag for a given Argument.
- // Returns an mpl::pair<> consisting of the tagged_argument<>,
- // and an mpl::set<> where the new tag has been inserted.
- //
- // Argument: The argument type to be tagged.
- //
- // ArgumentPack: The ArgumentPack built so far.
- //
- // DeducedArgs: A specialization of deduced_item<> (see below).
- // A list containing only the deduced ParameterSpecs.
- //
- // UsedArgs: An mpl::set<> containing the keyword tags used so far.
- //
- // TagFn: A metafunction class used to tag positional or deduced
- // arguments with a keyword tag.
-
- template <
- class Argument
- , class ArgumentPack
- , class DeducedArgs
- , class UsedArgs
- , class TagFn
- >
- struct deduce_tag
- {
- typedef typename mpl::eval_if<
- is_same<DeducedArgs, void_>
- , mpl::pair<void_, UsedArgs>
- , deduce_tag0<Argument, ArgumentPack, DeducedArgs, UsedArgs, TagFn>
- >::type type;
- };
-
- template <
- class List
- , class DeducedArgs
- , class TagFn
- , class Positional
- , class UsedArgs
- , class ArgumentPack
- , class Error
- >
- struct make_arg_list_aux;
-
- // Inserts Tagged::key_type into the UserArgs set.
- // Extra indirection to lazily evaluate Tagged::key_type.
- template <class UsedArgs, class Tagged>
- struct insert_tagged
- {
- typedef typename aux::insert_<
- UsedArgs, typename Tagged::key_type
- >::type type;
- };
-
- // Borland needs the insane extra-indirection workaround below
- // so that it doesn't magically drop the const qualifier from
- // the argument type.
-
- template <
- class List
- , class DeducedArgs
- , class TagFn
- , class Positional
- , class UsedArgs
- , class ArgumentPack
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- , class argument
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_if<
+ typename ::boost::parameter::aux::match_parameters_base_cond<
+ ArgumentPackAndError
+ , parameter_spec
+ >::type
+ , ::boost::mp11::mp_identity<
+ ::boost::parameter::parameters<Spec...>
+ >
+ , ::boost::parameter::void_
+ >;
#endif
- , class Error
- >
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- struct make_arg_list00
+ };
+
+ // Specializations are to be used as an optional argument
+ // to eliminate overloads via SFINAE.
+ template <typename ...Args>
+ struct match
+ : ::boost::parameter::parameters<Spec...>
+ ::BOOST_NESTED_TEMPLATE match_base<
+ typename ::boost::parameter::aux::make_arg_list<
+ typename ::boost::parameter::aux
+ ::make_parameter_spec_items<parameter_spec,Args...>::type
+ , deduced_list
+ , ::boost::parameter::aux::tag_keyword_arg
+ // Don't emit errors when doing SFINAE.
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ , ::boost::mp11::mp_false
#else
- struct make_arg_list0
+ , ::boost::mpl::false_
#endif
- {
-#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- typedef typename List::arg argument;
+ >::type
+ >::type
+ {
+ };
+
+ // Metafunction that returns an ArgumentPack.
+ template <typename ...Args>
+ struct bind
+#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mpl::first<
+ typename ::boost::parameter::aux::make_arg_list<
+ typename ::boost::parameter::aux
+ ::make_parameter_spec_items<parameter_spec,Args...>::type
+ , deduced_list
+ , ::boost::parameter::aux::tag_template_keyword_arg
+ >::type
+ >
#endif
- typedef typename List::spec parameter_spec;
- typedef typename tag_type<parameter_spec>::type tag_;
-
- typedef is_named_argument<argument> is_tagged;
-
- // If this argument is either explicitly tagged or a deduced
- // parameter, we turn off positional matching.
- typedef mpl::and_<
- mpl::not_<
- mpl::or_<is_deduced<parameter_spec>, is_tagged>
- >
- , Positional
- > positional;
-
- // If this parameter is explicitly tagged we add it to the
- // used-parmeters set. We only really need to add parameters
- // that are deduced, but we would need a way to check if
- // a given tag corresponds to a deduced parameter spec.
- typedef typename mpl::eval_if<
- is_tagged
- , insert_tagged<UsedArgs, argument>
- , mpl::identity<UsedArgs>
- >::type used_args;
-
- // If this parameter is neither explicitly tagged, nor
- // positionally matched; deduce the tag from the deduced
- // parameter specs.
- typedef typename mpl::eval_if<
- mpl::or_<is_tagged, positional>
- , mpl::pair<void_, used_args>
- , deduce_tag<argument, ArgumentPack, DeducedArgs, used_args, TagFn>
- >::type deduced_data;
-
- // If this parameter is explicitly tagged..
- typedef typename mpl::eval_if<
- is_tagged
- , mpl::identity<argument> // .. just use it
- , mpl::eval_if< // .. else, if positional matching is turned on..
- positional
- , mpl::apply_wrap2<TagFn, tag_, argument> // .. tag it positionally
- , mpl::first<deduced_data> // .. else, use the deduced tag
- >
- >::type tagged;
-
- // We build the arg_list incrementally as we go, prepending new
- // nodes.
-
- typedef typename mpl::if_<
- mpl::and_<
- is_same<Error, void_>
- , is_same<tagged, void_>
- >
- , parameter_::unmatched_argument<argument>
- , void_
- >::type error;
-
- typedef typename mpl::if_<
- is_same<tagged, void_>
- , ArgumentPack
- , arg_list<tagged, ArgumentPack>
- >::type argument_pack;
-
- typedef typename make_arg_list_aux<
- typename List::tail
- , DeducedArgs
- , TagFn
- , positional
- , typename deduced_data::second
- , argument_pack
- , error
- >::type type;
- };
-
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- template <
- class List
- , class DeducedArgs
- , class TagFn
- , class Positional
- , class UsedArgs
- , class ArgumentPack
- , class Error
- >
- struct make_arg_list0
- {
- typedef typename mpl::eval_if<
- typename List::is_arg_const
- , make_arg_list00<
- List
- , DeducedArgs
- , TagFn
- , Positional
- , UsedArgs
- , ArgumentPack
- , typename List::arg const
- , Error
- >
- , make_arg_list00<
- List
- , DeducedArgs
- , TagFn
- , Positional
- , UsedArgs
- , ArgumentPack
- , typename List::arg
- , Error
- >
- >::type type;
- };
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_at_c<
+ typename ::boost::parameter::aux::make_arg_list<
+ typename ::boost::parameter::aux
+ ::make_parameter_spec_items<parameter_spec,Args...>::type
+ , deduced_list
+ , ::boost::parameter::aux::tag_template_keyword_arg
+ >::type
+ , 0
+ >;
#endif
+ };
+
+ // The function call operator is used to build an arg_list that
+ // labels the positional parameters and maintains whatever other
+ // tags may have been specified by the caller.
+ inline ::boost::parameter::aux::empty_arg_list operator()() const
+ {
+ return ::boost::parameter::aux::empty_arg_list();
+ }
+
+ template <typename A0, typename ...Args>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ inline ::boost::mp11::mp_at_c<
+#else
+ inline typename ::boost::mpl::first<
+#endif
+ typename ::boost::parameter::aux::make_arg_list<
+ typename ::boost::parameter::aux
+ ::make_parameter_spec_items<parameter_spec,A0,Args...>::type
+ , deduced_list
+ , ::boost::parameter::aux::tag_keyword_arg
+ >::type
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ , 0
+ >
+#else
+ >::type
+#endif
+ operator()(A0&& a0, Args&& ...args) const
+ {
+ typedef typename ::boost::parameter::aux::make_arg_list<
+ typename ::boost::parameter::aux
+ ::make_parameter_spec_items<parameter_spec,A0,Args...>::type
+ , deduced_list
+ , ::boost::parameter::aux::tag_keyword_arg
+ >::type list_error_pair;
- // Returns an ArgumentPack where the list of arguments has
- // been tagged with keyword tags.
- //
- // List: A specialization of item<> (see below). Contains
- // both the ordered ParameterSpecs, and the given arguments.
- //
- // DeducedArgs: A specialization of deduced_item<> (see below).
- // A list containing only the deduced ParameterSpecs.
- //
- // TagFn: A metafunction class used to tag positional or deduced
- // arguments with a keyword tag.
- //
- // Position: An mpl::bool_<> specialization indicating if positional
- // matching is to be performed.
- //
- // DeducedSet: An mpl::set<> containing the keyword tags used so far.
- //
- // ArgumentPack: The ArgumentPack built so far. This is initially an
- // empty_arg_list and is built incrementally.
- //
-
- template <
- class List
- , class DeducedArgs
- , class TagFn
- , class Positional
- , class DeducedSet
- , class ArgumentPack
- , class Error
- >
- struct make_arg_list_aux
- {
- typedef typename mpl::eval_if<
- is_same<List, void_>
- , mpl::identity<mpl::pair<ArgumentPack, Error> >
- , make_arg_list0<List, DeducedArgs, TagFn, Positional, DeducedSet, ArgumentPack, Error>
- >::type type;
- };
-
- // VC6.5 was choking on the default parameters for make_arg_list_aux, so
- // this just forwards to that adding in the defaults.
- template <
- class List
- , class DeducedArgs
- , class TagFn
- , class EmitErrors = mpl::true_
- >
- struct make_arg_list
- {
- typedef typename make_arg_list_aux<
- List, DeducedArgs, TagFn, mpl::true_, aux::set0, empty_arg_list, void_
- >::type type;
- };
-
- // A parameter spec item typelist.
- template <class Spec, class Arg, class Tail = void_>
- struct item
- {
- typedef Spec spec;
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using result_type = ::boost::mp11::mp_at_c<list_error_pair,0>;
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- typedef is_const<Arg> is_arg_const;
+ using error = ::boost::mp11::mp_at_c<list_error_pair,1>;
+#else
+ typedef typename ::boost::mpl
+ ::first<list_error_pair>::type result_type;
+
+ typedef typename ::boost::mpl
+ ::second<list_error_pair>::type error;
#endif
- typedef Arg arg;
- typedef Tail tail;
- };
-
- template <class Spec, class Arg, class Tail>
- struct make_item
- {
- typedef item<Spec, Arg, typename Tail::type> type;
- };
-
- // Creates a item typelist.
- template <class Spec, class Arg, class Tail>
- struct make_items
- {
- typedef typename mpl::eval_if<
- is_same<Arg, void_>
- , mpl::identity<void_>
- , make_item<Spec, Arg, Tail>
- >::type type;
- };
-
- // A typelist that stored deduced parameter specs.
- template <class ParameterSpec, class Tail = void_>
- struct deduced_item
- {
- typedef ParameterSpec spec;
- typedef Tail tail;
- };
-
- // Evaluate Tail and construct deduced_item list.
- template <class Spec, class Tail>
- struct make_deduced_item
- {
- typedef deduced_item<Spec, typename Tail::type> type;
- };
-
- template <class Spec, class Tail>
- struct make_deduced_items
- {
- typedef typename mpl::eval_if<
- is_same<Spec, void_>
- , mpl::identity<void_>
- , mpl::eval_if<
- is_deduced<Spec>
- , make_deduced_item<Spec, Tail>
- , Tail
- >
- >::type type;
- };
-
- // Generates:
- //
- // make<
- // parameter_spec#0, argument_type#0
- // , make<
- // parameter_spec#1, argument_type#1
- // , ... mpl::identity<aux::empty_arg_list>
- // ...>
- // >
-#define BOOST_PARAMETER_make_arg_list(z, n, names) \
- BOOST_PP_SEQ_ELEM(0,names)< \
- BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names), n), \
- BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(2,names), n),
-
-#define BOOST_PARAMETER_right_angle(z, n, text) >
-
-#define BOOST_PARAMETER_build_arg_list(n, make, parameter_spec, argument_type) \
- BOOST_PP_REPEAT( \
- n, BOOST_PARAMETER_make_arg_list, (make)(parameter_spec)(argument_type)) \
- mpl::identity<void_> \
- BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _)
-
-#define BOOST_PARAMETER_make_deduced_list(z, n, names) \
- BOOST_PP_SEQ_ELEM(0,names)< \
- BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names), n),
-
-#define BOOST_PARAMETER_build_deduced_list(n, make, parameter_spec) \
- BOOST_PP_REPEAT( \
- n, BOOST_PARAMETER_make_deduced_list, (make)(parameter_spec)) \
- mpl::identity<void_> \
- BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _)
-
- struct tag_keyword_arg
- {
- template <class K, class T>
- struct apply
- : tag<K,T>
- {};
- };
-
- struct tag_template_keyword_arg
- {
- template <class K, class T>
- struct apply
- {
- typedef template_keyword<K,T> type;
- };
- };
-
-} // namespace aux
-
-#define BOOST_PARAMETER_FORWARD_TYPEDEF(z, i, names) \
- typedef BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0,names),i) BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names),i);
-
-#define BOOST_PARAMETER_FORWARD_TYPEDEFS(n, src, dest) \
- BOOST_PP_REPEAT(n, BOOST_PARAMETER_FORWARD_TYPEDEF, (src)(dest))
-
-
-#define BOOST_PARAMETER_TEMPLATE_ARGS(z, n, text) class BOOST_PP_CAT(PS, n) = void_
-
-template<
- class PS0
- , BOOST_PP_ENUM_SHIFTED(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_TEMPLATE_ARGS, _)
->
-struct parameters
-{
-#undef BOOST_PARAMETER_TEMPLATE_ARGS
-
- typedef typename BOOST_PARAMETER_build_deduced_list(
- BOOST_PARAMETER_MAX_ARITY, aux::make_deduced_items, PS
- )::type deduced_list;
-
- // if the elements of NamedList match the criteria of overload
- // resolution, returns a type which can be constructed from
- // parameters. Otherwise, this is not a valid metafunction (no nested
- // ::type).
-
-
-#if ! defined(BOOST_NO_SFINAE) && ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
- // If NamedList satisfies the PS0, PS1, ..., this is a
- // metafunction returning parameters. Otherwise it
- // has no nested ::type.
- template <class ArgumentPackAndError>
- struct match_base
- : mpl::if_<
- // mpl::and_<
- // aux::satisfies_requirements_of<NamedList,PS0>
- // , mpl::and_<
- // aux::satisfies_requirements_of<NamedList,PS1>...
- // ..., mpl::true_
- // ...> >
-
-# define BOOST_PARAMETER_satisfies(z, n, text) \
- mpl::and_< \
- aux::satisfies_requirements_of< \
- typename mpl::first<ArgumentPackAndError>::type \
- , BOOST_PP_CAT(PS, n)> \
- ,
- mpl::and_<
- is_same<typename mpl::second<ArgumentPackAndError>::type, void_>
- , BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_satisfies, _)
- mpl::true_
- BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_right_angle, _)
- >
+ error();
-# undef BOOST_PARAMETER_satisfies
+ return ::boost::parameter::aux
+ ::arg_list_factory<result_type,A0,Args...>::reverse(
+ ::std::forward<A0>(a0)
+ , ::std::forward<Args>(args)...
+ );
+ }
+ };
+}} // namespace boost::parameter
- , mpl::identity<parameters>
- , void_
- >
- {};
+#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/parameter/aux_/arg_list.hpp>
+#include <boost/parameter/aux_/pack/make_arg_list.hpp>
+#include <boost/parameter/aux_/pack/make_items.hpp>
+#include <boost/parameter/aux_/pack/make_deduced_items.hpp>
+#include <boost/parameter/aux_/pack/tag_template_keyword_arg.hpp>
+#include <boost/parameter/aux_/preprocessor/binary_seq_for_each.hpp>
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/repetition/enum_shifted.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/selection/min.hpp>
+
+#if ( \
+ BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < \
+ BOOST_PARAMETER_MAX_ARITY \
+ )
+#include <boost/parameter/aux_/pack/tag_keyword_arg_ref.hpp>
+#include <boost/mpl/pair.hpp>
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/facilities/intercept.hpp>
+#include <boost/preprocessor/iteration/iterate.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+#endif
+
+#if !defined(BOOST_NO_SFINAE) && \
+ !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
+#include <boost/parameter/aux_/pack/tag_keyword_arg.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/type_traits/is_same.hpp>
#endif
-
- // Specializations are to be used as an optional argument to
- // eliminate overloads via SFINAE
- template<
+
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- // Borland simply can't handle default arguments in member
- // class templates. People wishing to write portable code can
- // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments
- BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, class A)
-#else
- BOOST_PP_ENUM_BINARY_PARAMS(
- BOOST_PARAMETER_MAX_ARITY, class A, = void_ BOOST_PP_INTERCEPT
- )
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#else
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#endif
+
+#include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_begin.hpp>
+
+namespace boost { namespace parameter {
+
+ template <
+ typename PS0
+ , BOOST_PP_ENUM_SHIFTED(
+ BOOST_PARAMETER_MAX_ARITY
+ , BOOST_PARAMETER_template_args
+ , PS
+ )
>
- struct match
-# if ! defined(BOOST_NO_SFINAE) && ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
- : match_base<
- typename aux::make_arg_list<
- typename BOOST_PARAMETER_build_arg_list(
- BOOST_PARAMETER_MAX_ARITY, aux::make_items, PS, A
+ struct parameters
+ {
+ typedef typename BOOST_PARAMETER_build_deduced_list(
+ BOOST_PARAMETER_MAX_ARITY
+ , ::boost::parameter::aux::make_deduced_items
+ , PS
+ )::type deduced_list;
+
+ // If the elements of NamedList match the criteria of overload
+ // resolution, returns a type which can be constructed from
+ // parameters. Otherwise, this is not a valid metafunction
+ // (no nested ::type).
+#if !defined(BOOST_NO_SFINAE) && \
+ !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
+ // If NamedList satisfies the PS0, PS1, ..., this is a metafunction
+ // returning parameters. Otherwise it has no nested ::type.
+ template <typename ArgumentPackAndError>
+ struct match_base
+ : ::boost::mpl::if_<
+ // ::boost::mpl::and_<
+ // aux::satisfies_requirements_of<NamedList,PS0>
+ // , ::boost::mpl::and_<
+ // aux::satisfies_requirements_of<NamedList,PS1>...
+ // ..., ::boost::mpl::true_
+ // ...> >
+ typename BOOST_PP_REPEAT(
+ BOOST_PARAMETER_MAX_ARITY
+ , BOOST_PARAMETER_satisfies_begin
+ , PS
+ )
+ ::boost::is_same<
+ typename ::boost::mpl
+ ::second<ArgumentPackAndError>::type
+ , ::boost::parameter::void_
+ >
+ BOOST_PP_REPEAT(
+ BOOST_PARAMETER_MAX_ARITY
+ , BOOST_PARAMETER_satisfies_end
+ , ::boost::mpl::false_
)::type
- , deduced_list
- , aux::tag_keyword_arg
- , mpl::false_ // Don't emit errors when doing SFINAE
+ , ::boost::mpl::identity<
+ ::boost::parameter::parameters<
+ BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)
+ >
+ >
+ , ::boost::parameter::void_
+ >
+ {
+ };
+#endif // SFINAE enabled, not Borland
+
+ // Specializations are to be used as an optional argument
+ // to eliminate overloads via SFINAE.
+ template <
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ // Borland simply can't handle default arguments in member
+ // class templates. People wishing to write portable code can
+ // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments.
+ BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, typename A)
+#else
+ BOOST_PP_ENUM_BINARY_PARAMS(
+ BOOST_PARAMETER_MAX_ARITY
+ , typename A
+ , = ::boost::parameter::void_ BOOST_PP_INTERCEPT
+ )
+#endif
+ >
+ struct match
+#if !defined(BOOST_NO_SFINAE) && \
+ !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
+ : ::boost::parameter::parameters<
+ BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)
+ >::BOOST_NESTED_TEMPLATE match_base<
+ typename ::boost::parameter::aux::make_arg_list<
+ typename BOOST_PARAMETER_build_arg_list(
+ BOOST_PARAMETER_MAX_ARITY
+ , ::boost::parameter::aux::make_items
+ , PS
+ , A
+ )::type
+ , deduced_list
+ , ::boost::parameter::aux::tag_keyword_arg
+ // Don't emit errors when doing SFINAE.
+ , ::boost::mpl::false_
+ >::type
>::type
- >::type
- {};
-# else
- {
- typedef parameters<
- BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)
- > type;
- };
-# endif
+ {
+ };
+#else
+ {
+ typedef ::boost::parameter::parameters<
+ BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)
+ > type;
+ };
+#endif // SFINAE enabled, not Borland
- // Metafunction that returns an ArgumentPack.
+ // Metafunction that returns an ArgumentPack.
- // TODO, bind has to instantiate the error type in the result
- // of make_arg_list.
+ // TODO, bind has to instantiate the error type in the result
+ // of make_arg_list.
- template <
+ template <
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- // Borland simply can't handle default arguments in member
- // class templates. People wishing to write portable code can
- // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments
- BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, class A)
-#else
- BOOST_PP_ENUM_BINARY_PARAMS(
- BOOST_PARAMETER_MAX_ARITY, class A, = void_ BOOST_PP_INTERCEPT
+ // Borland simply can't handle default arguments in member
+ // class templates. People wishing to write portable code can
+ // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments.
+ BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, typename A)
+#else
+ BOOST_PP_ENUM_BINARY_PARAMS(
+ BOOST_PARAMETER_MAX_ARITY
+ , typename A
+ , = ::boost::parameter::void_ BOOST_PP_INTERCEPT
+ )
+#endif
+ >
+ struct bind
+ {
+ typedef typename ::boost::parameter::aux::make_arg_list<
+ typename BOOST_PARAMETER_build_arg_list(
+ BOOST_PARAMETER_MAX_ARITY
+ , ::boost::parameter::aux::make_items
+ , PS
+ , A
+ )::type
+ , deduced_list
+ , ::boost::parameter::aux::tag_template_keyword_arg
+ >::type result;
+
+ typedef typename ::boost::mpl::first<result>::type type;
+ };
+
+ BOOST_PP_REPEAT(
+ BOOST_PARAMETER_MAX_ARITY
+ , BOOST_PARAMETER_forward_typedef
+ , (PS)(parameter_spec)
)
-#endif
- >
- struct bind
- {
- typedef typename aux::make_arg_list<
- typename BOOST_PARAMETER_build_arg_list(
- BOOST_PARAMETER_MAX_ARITY, aux::make_items, PS, A
- )::type
- , deduced_list
- , aux::tag_template_keyword_arg
- >::type result;
-
- typedef typename mpl::first<result>::type type;
- };
- BOOST_PARAMETER_FORWARD_TYPEDEFS(BOOST_PARAMETER_MAX_ARITY, PS, parameter_spec)
-
- //
- // The function call operator is used to build an arg_list that
- // labels the positional parameters and maintains whatever other
- // tags may have been specified by the caller.
- //
- // !!!NOTE!!!
- //
- // The make_arg_list<> produces a reversed arg_list, so
- // we need to pass the arguments to its constructor
- // reversed.
- //
- aux::empty_arg_list operator()() const
- {
- return aux::empty_arg_list();
- }
-
- template<class A0>
- typename mpl::first<
- typename aux::make_arg_list<
- aux::item<
- PS0,A0
- >
- , deduced_list
- , aux::tag_keyword_arg
+ // The function call operator is used to build an arg_list that
+ // labels the positional parameters and maintains whatever other
+ // tags may have been specified by the caller.
+ //
+ // !!!NOTE!!!
+ //
+ // The make_arg_list<> metafunction produces a reversed arg_list,
+ // so pass the arguments to the arg_list constructor reversed in turn.
+ inline ::boost::parameter::aux::empty_arg_list operator()() const
+ {
+ return ::boost::parameter::aux::empty_arg_list();
+ }
+
+#if (0 < BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY)
+ BOOST_PP_REPEAT(
+ BOOST_PP_MIN(
+ BOOST_PP_INC(BOOST_PARAMETER_MAX_ARITY)
+ , BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY
+ )
+ , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_Z
+ , (BOOST_PARAMETER_function_call_op_overload_R)(_)
+ )
+#if ( \
+ BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < \
+ BOOST_PARAMETER_MAX_ARITY \
+ )
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,( \
+ BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY \
+ , BOOST_PARAMETER_MAX_ARITY \
+ , <boost/parameter/aux_/preprocessor/overloads.hpp> \
+ ))
+#include BOOST_PP_ITERATE()
+#endif
+#else // (0 == BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY)
+ template <typename A0>
+ inline typename ::boost::mpl::first<
+ typename ::boost::parameter::aux::make_arg_list<
+ ::boost::parameter::aux::item<
+ PS0,A0
+ >
+ , deduced_list
+ , ::boost::parameter::aux::tag_keyword_arg_ref
+ >::type
>::type
- >::type
- operator()(A0& a0) const
- {
- typedef typename aux::make_arg_list<
- aux::item<
- PS0,A0
- >
- , deduced_list
- , aux::tag_keyword_arg
- >::type result;
-
- typedef typename mpl::first<result>::type result_type;
- typedef typename mpl::second<result>::type error;
- error();
-
- return result_type(
- a0
- // , void_(), void_(), void_() ...
- BOOST_PP_ENUM_TRAILING_PARAMS(
- BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, 1)
- , aux::void_reference() BOOST_PP_INTERCEPT)
- );
- }
-
- template<class A0, class A1>
- typename mpl::first<
- typename aux::make_arg_list<
- aux::item<
- PS0,A0
- , aux::item<
- PS1,A1
+ operator()(A0& a0) const
+ {
+ typedef typename ::boost::parameter::aux::make_arg_list<
+ ::boost::parameter::aux::item<
+ PS0,A0
>
- >
- , deduced_list
- , aux::tag_keyword_arg
+ , deduced_list
+ , ::boost::parameter::aux::tag_keyword_arg_ref
+ >::type result;
+
+ typedef typename ::boost::mpl::first<result>::type result_type;
+ typedef typename ::boost::mpl::second<result>::type error;
+ error();
+
+ return result_type(
+ a0
+ // , void_(), void_(), void_() ...
+ BOOST_PP_ENUM_TRAILING_PARAMS(
+ BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, 1)
+ , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT
+ )
+ );
+ }
+
+ template <typename A0, typename A1>
+ inline typename ::boost::mpl::first<
+ typename ::boost::parameter::aux::make_arg_list<
+ ::boost::parameter::aux::item<
+ PS0,A0
+ , ::boost::parameter::aux::item<
+ PS1,A1
+ >
+ >
+ , deduced_list
+ , ::boost::parameter::aux::tag_keyword_arg_ref
+ >::type
>::type
- >::type
- operator()(A0& a0, A1& a1) const
- {
- typedef typename aux::make_arg_list<
- aux::item<
- PS0,A0
- , aux::item<
- PS1,A1
+ operator()(A0& a0, A1& a1) const
+ {
+ typedef typename ::boost::parameter::aux::make_arg_list<
+ ::boost::parameter::aux::item<
+ PS0,A0
+ , ::boost::parameter::aux::item<
+ PS1,A1
+ >
>
- >
- , deduced_list
- , aux::tag_keyword_arg
- >::type result;
-
- typedef typename mpl::first<result>::type result_type;
- typedef typename mpl::second<result>::type error;
- error();
-
- return result_type(
- a1,a0
- // , void_(), void_() ...
- BOOST_PP_ENUM_TRAILING_PARAMS(
- BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, 2)
- , aux::void_reference() BOOST_PP_INTERCEPT)
- );
- }
-
- // Higher arities are handled by the preprocessor
-#define BOOST_PP_ITERATION_PARAMS_1 (3,( \
- 3,BOOST_PARAMETER_MAX_ARITY,<boost/parameter/aux_/overloads.hpp> \
+ , deduced_list
+ , ::boost::parameter::aux::tag_keyword_arg
+ >::type result;
+
+ typedef typename ::boost::mpl::first<result>::type result_type;
+ typedef typename ::boost::mpl::second<result>::type error;
+ error();
+
+ return result_type(
+ a1
+ , a0
+ // , void_(), void_() ...
+ BOOST_PP_ENUM_TRAILING_PARAMS(
+ BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, 2)
+ , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT
+ )
+ );
+ }
+
+#if (2 < BOOST_PARAMETER_MAX_ARITY)
+ // Higher arities are handled by the preprocessor
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,( \
+ 3 \
+ , BOOST_PARAMETER_MAX_ARITY \
+ , <boost/parameter/aux_/preprocessor/overloads.hpp> \
))
#include BOOST_PP_ITERATE()
+#endif
+#endif // exponential overloads
+ };
+}} // namespace boost::parameter
-};
-
-} // namespace parameter
-
-} // namespace boost
+#include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_end.hpp>
-#endif // BOOST_PARAMETERS_031014_HPP
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+#endif // include guard
diff --git a/boost/parameter/preprocessor.hpp b/boost/parameter/preprocessor.hpp
index 8ea370cb4b..c67e18a073 100644
--- a/boost/parameter/preprocessor.hpp
+++ b/boost/parameter/preprocessor.hpp
@@ -1,1077 +1,217 @@
-// Copyright Daniel Wallin 2006. Use, modification and distribution is
-// subject to the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright Daniel Wallin 2006.
+// Copyright Cromwell D. Enage 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_PARAMETER_PREPROCESSOR_060206_HPP
-# define BOOST_PARAMETER_PREPROCESSOR_060206_HPP
+#define BOOST_PARAMETER_PREPROCESSOR_060206_HPP
-# include <boost/parameter/parameters.hpp>
-# include <boost/parameter/binding.hpp>
-# include <boost/parameter/match.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/forwarding_overloads.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/specification.hpp>
+#include <boost/preprocessor/cat.hpp>
-# include <boost/parameter/aux_/parenthesized_type.hpp>
-# include <boost/parameter/aux_/cast.hpp>
-# include <boost/parameter/aux_/preprocessor/flatten.hpp>
-
-# include <boost/preprocessor/repetition/repeat_from_to.hpp>
-# include <boost/preprocessor/comparison/equal.hpp>
-# include <boost/preprocessor/control/if.hpp>
-# include <boost/preprocessor/control/iif.hpp>
-# include <boost/preprocessor/control/expr_if.hpp>
-# include <boost/preprocessor/repetition/enum_params.hpp>
-# include <boost/preprocessor/repetition/enum_binary_params.hpp>
-# include <boost/preprocessor/repetition/enum_trailing.hpp>
-# include <boost/preprocessor/seq/first_n.hpp>
-# include <boost/preprocessor/seq/for_each_product.hpp>
-# include <boost/preprocessor/seq/for_each_i.hpp>
-# include <boost/preprocessor/tuple/elem.hpp>
-# include <boost/preprocessor/tuple/eat.hpp>
-# include <boost/preprocessor/seq/fold_left.hpp>
-# include <boost/preprocessor/seq/push_back.hpp>
-# include <boost/preprocessor/seq/size.hpp>
-# include <boost/preprocessor/seq/enum.hpp>
-# include <boost/preprocessor/seq/push_back.hpp>
-
-# include <boost/preprocessor/detail/is_nullary.hpp>
-
-# include <boost/mpl/always.hpp>
-# include <boost/mpl/apply_wrap.hpp>
-
-namespace boost { namespace parameter { namespace aux {
-
-# if ! defined(BOOST_NO_SFINAE) && ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
-
-// Given Match, which is "void x" where x is an argument matching
-// criterion, extract a corresponding MPL predicate.
-template <class Match>
-struct unwrap_predicate;
-
-// Match anything
-template <>
-struct unwrap_predicate<void*>
-{
- typedef mpl::always<mpl::true_> type;
-};
-
-#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580))
-
-typedef void* voidstar;
-
-// A matching predicate is explicitly specified
-template <class Predicate>
-struct unwrap_predicate<voidstar (Predicate)>
-{
- typedef Predicate type;
-};
-
-#else
-
-// A matching predicate is explicitly specified
-template <class Predicate>
-struct unwrap_predicate<void *(Predicate)>
-{
- typedef Predicate type;
-};
-
-#endif
-
-
-// A type to which the argument is supposed to be convertible is
-// specified
-template <class Target>
-struct unwrap_predicate<void (Target)>
-{
- typedef is_convertible<mpl::_, Target> type;
-};
-
-// Recast the ParameterSpec's nested match metafunction as a free metafunction
-template <
- class Parameters
- , BOOST_PP_ENUM_BINARY_PARAMS(
- BOOST_PARAMETER_MAX_ARITY, class A, = boost::parameter::void_ BOOST_PP_INTERCEPT
- )
->
-struct match
- : Parameters::template match<
- BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, A)
- >
-{};
-# endif
-
-# undef false_
-
-template <
- class Parameters
- , BOOST_PP_ENUM_BINARY_PARAMS(
- BOOST_PARAMETER_MAX_ARITY, class A, = boost::parameter::void_ BOOST_PP_INTERCEPT
- )
->
-struct argument_pack
-{
- typedef typename make_arg_list<
- typename BOOST_PARAMETER_build_arg_list(
- BOOST_PARAMETER_MAX_ARITY, make_items, typename Parameters::parameter_spec, A
- )::type
- , typename Parameters::deduced_list
- , tag_keyword_arg
- , mpl::false_
- >::type result;
- typedef typename mpl::first<result>::type type;
-};
-
-// Works around VC6 problem where it won't accept rvalues.
-template <class T>
-T& as_lvalue(T& value, long)
-{
- return value;
-}
-
-template <class T>
-T const& as_lvalue(T const& value, int)
-{
- return value;
-}
-
-
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-
-template <class Predicate, class T, class Args>
-struct apply_predicate
-{
- BOOST_MPL_ASSERT((
- mpl::and_<mpl::false_,T>
- ));
-
- typedef typename mpl::if_<
- typename mpl::apply2<Predicate,T,Args>::type
- , char
- , int
- >::type type;
-};
-
-template <class P>
-struct funptr_predicate
-{
- static P p;
-
- template <class T, class Args, class P0>
- static typename apply_predicate<P0,T,Args>::type
- check_predicate(type<T>, Args*, void**(*)(P0));
-
- template <class T, class Args, class P0>
- static typename mpl::if_<
- is_convertible<T,P0>
- , char
- , int
- >::type check_predicate(type<T>, Args*, void*(*)(P0));
-
- template <class T, class Args>
- struct apply
- {
- BOOST_STATIC_CONSTANT(bool, result =
- sizeof(check_predicate(boost::type<T>(), (Args*)0, &p)) == 1
- );
-
- typedef mpl::bool_<apply<T,Args>::result> type;
- };
-};
-
-template <>
-struct funptr_predicate<void**>
- : mpl::always<mpl::true_>
-{};
-
-# endif
-
-}}} // namespace boost::parameter::aux
-
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-// From Paul Mensonides
-# define BOOST_PARAMETER_IS_NULLARY(x) \
- BOOST_PP_SPLIT(1, BOOST_PARAMETER_IS_NULLARY_C x BOOST_PP_COMMA() 0) \
- /**/
-# define BOOST_PARAMETER_IS_NULLARY_C() \
- ~, 1 BOOST_PP_RPAREN() \
- BOOST_PP_TUPLE_EAT(2) BOOST_PP_LPAREN() ~ \
- /**/
-# else
-# define BOOST_PARAMETER_IS_NULLARY(x) BOOST_PP_IS_NULLARY(x)
-# endif
-
-# define BOOST_PARAMETER_MEMBER_FUNCTION_CHECK_STATIC_static ()
-# define BOOST_PARAMETER_MEMBER_FUNCTION_IS_STATIC(name) \
- BOOST_PARAMETER_IS_NULLARY( \
- BOOST_PP_CAT(BOOST_PARAMETER_MEMBER_FUNCTION_CHECK_STATIC_,name) \
- )
-
-# if !defined(BOOST_MSVC)
-# define BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_static
-# define BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC(name) \
- BOOST_PP_CAT(BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_, name)
-# else
-// Workaround for MSVC preprocessor.
-//
-// When stripping static from "static f", msvc will produce
-// " f". The leading whitespace doesn't go away when pasting
-// the token with something else, so this thing is a hack to
-// strip the whitespace.
-# define BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_static (
-# define BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_AUX(name) \
- BOOST_PP_CAT(BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_, name))
-# define BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC(name) \
- BOOST_PP_SEQ_HEAD( \
- BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC_AUX(name) \
- )
-# endif
-
-# define BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(name) \
- BOOST_PP_EXPR_IF( \
- BOOST_PARAMETER_MEMBER_FUNCTION_IS_STATIC(name) \
- , static \
- )
-
-# define BOOST_PARAMETER_MEMBER_FUNCTION_NAME(name) \
- BOOST_PP_IF( \
- BOOST_PARAMETER_MEMBER_FUNCTION_IS_STATIC(name) \
- , BOOST_PARAMETER_MEMBER_FUNCTION_STRIP_STATIC \
- , name BOOST_PP_TUPLE_EAT(1) \
- )(name)
-
-// Calculates [begin, end) arity range.
-
-# define BOOST_PARAMETER_ARITY_RANGE_M_optional(state) state
-# define BOOST_PARAMETER_ARITY_RANGE_M_deduced_optional(state) state
-# define BOOST_PARAMETER_ARITY_RANGE_M_required(state) BOOST_PP_INC(state)
-# define BOOST_PARAMETER_ARITY_RANGE_M_deduced_required(state) BOOST_PP_INC(state)
-
-# define BOOST_PARAMETER_ARITY_RANGE_M(s, state, x) \
- BOOST_PP_CAT( \
- BOOST_PARAMETER_ARITY_RANGE_M_ \
- , BOOST_PARAMETER_FN_ARG_QUALIFIER(x) \
- )(state)
+// Helper macro for BOOST_PARAMETER_CONSTRUCTOR.
+#define BOOST_PARAMETER_CONSTRUCTOR_AUX(class_, base, tag_namespace, args) \
+ BOOST_PARAMETER_SPECIFICATION(tag_namespace, ctor, args, 0) \
+ BOOST_PP_CAT(constructor_parameters, __LINE__); \
+ BOOST_PARAMETER_CONSTRUCTOR_OVERLOADS(class_, base, args)
/**/
-# define BOOST_PARAMETER_ARITY_RANGE(args) \
- ( \
- BOOST_PP_SEQ_FOLD_LEFT(BOOST_PARAMETER_ARITY_RANGE_M, 0, args) \
- , BOOST_PP_INC(BOOST_PP_SEQ_SIZE(args)) \
- )
-/**/
+#include <boost/parameter/aux_/preprocessor/impl/function_name.hpp>
-// Accessor macros for the argument specs tuple.
-# define BOOST_PARAMETER_FN_ARG_QUALIFIER(x) \
- BOOST_PP_TUPLE_ELEM(4,0,x)
-/**/
-
-# define BOOST_PARAMETER_FN_ARG_NAME(x) \
- BOOST_PP_TUPLE_ELEM(4,1,x)
-/**/
-
-# define BOOST_PARAMETER_FN_ARG_PRED(x) \
- BOOST_PP_TUPLE_ELEM(4,2,x)
-/**/
-
-# define BOOST_PARAMETER_FN_ARG_DEFAULT(x) \
- BOOST_PP_TUPLE_ELEM(4,3,x)
+// Defines the implementation function header.
+#define BOOST_PARAMETER_FUNCTION_IMPL_HEAD(name, is_const) \
+ template <typename Args> \
+ typename BOOST_PARAMETER_FUNCTION_RESULT_NAME(name, is_const)< \
+ Args \
+ >::type BOOST_PARAMETER_FUNCTION_IMPL_NAME(name, is_const)( \
+ Args const& args \
+ )
/**/
-# define BOOST_PARAMETETER_FUNCTION_EAT_KEYWORD_QUALIFIER_out(x)
-# define BOOST_PARAMETETER_FUNCTION_EAT_KEYWORD_QUALIFIER_in_out(x)
+#include <boost/parameter/aux_/preprocessor/impl/parenthesized_return_type.hpp>
+#include <boost/parameter/config.hpp>
-// Returns 1 if x is either "out(k)" or "in_out(k)".
-# define BOOST_PARAMETER_FUNCTION_IS_KEYWORD_QUALIFIER(x) \
- BOOST_PP_IS_EMPTY( \
- BOOST_PP_CAT(BOOST_PARAMETETER_FUNCTION_EAT_KEYWORD_QUALIFIER_, x) \
- ) \
+// Expands to the result metafunction and the parameters specialization.
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#define BOOST_PARAMETER_FUNCTION_HEAD(result, name, tag_ns, args, is_const) \
+ template <typename Args> \
+ using BOOST_PARAMETER_FUNCTION_RESULT_NAME(name, is_const) \
+ = typename BOOST_PARAMETER_PARENTHESIZED_RETURN_TYPE(result); \
+ BOOST_PARAMETER_SPECIFICATION(tag_ns, name, args, is_const) \
+ BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME(name, is_const);
/**/
-
-# define BOOST_PARAMETETER_FUNCTION_GET_KEYWORD_QUALIFIER_out(x) x
-# define BOOST_PARAMETETER_FUNCTION_GET_KEYWORD_QUALIFIER_in_out(x) x
-# define BOOST_PARAMETER_FUNCTION_KEYWORD_GET(x) \
- BOOST_PP_CAT(BOOST_PARAMETETER_FUNCTION_GET_KEYWORD_QUALIFIER_, x)
+#else
+#define BOOST_PARAMETER_FUNCTION_HEAD(result, name, tag_ns, args, is_const) \
+ template <typename Args> \
+ struct BOOST_PARAMETER_FUNCTION_RESULT_NAME(name, is_const) \
+ : BOOST_PARAMETER_PARENTHESIZED_RETURN_TYPE(result) \
+ { \
+ }; \
+ BOOST_PARAMETER_SPECIFICATION(tag_ns, name, args, is_const) \
+ BOOST_PARAMETER_FUNCTION_SPECIFICATION_NAME(name, is_const);
/**/
+#endif // BOOST_PARAMETER_CAN_USE_MP11
-// Returns the keyword of x, where x is either a keyword qualifier
-// or a keyword.
-//
-// k => k
-// out(k) => k
-// in_out(k) => k
-//
-# define BOOST_PARAMETER_FUNCTION_KEYWORD(x) \
- BOOST_PP_IF( \
- BOOST_PARAMETER_FUNCTION_IS_KEYWORD_QUALIFIER(x) \
- , BOOST_PARAMETER_FUNCTION_KEYWORD_GET \
- , x BOOST_PP_TUPLE_EAT(1) \
- )(x)
+// Helper macro for BOOST_PARAMETER_BASIC_FUNCTION.
+#define BOOST_PARAMETER_BASIC_FUNCTION_AUX(result, name, tag_ns, args) \
+ BOOST_PARAMETER_FUNCTION_HEAD(result, name, tag_ns, args, 0) \
+ BOOST_PARAMETER_FUNCTION_IMPL_HEAD(name, 0); \
+ BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS(name, name, args, 0, 0) \
+ BOOST_PARAMETER_FUNCTION_IMPL_HEAD(name, 0)
/**/
-# define BOOST_PARAMETER_FN_ARG_KEYWORD(x) \
- BOOST_PARAMETER_FUNCTION_KEYWORD( \
- BOOST_PARAMETER_FN_ARG_NAME(x) \
- )
+#include <boost/preprocessor/control/expr_if.hpp>
-// Builds forwarding functions.
-
-# define BOOST_PARAMETER_FUNCTION_FWD_FUNCTION_TEMPLATE_Z(z, n) \
- template<BOOST_PP_ENUM_PARAMS_Z(z, n, class ParameterArgumentType)>
+// Helper macro for BOOST_PARAMETER_BASIC_MEMBER_FUNCTION,
+// BOOST_PARAMETER_BASIC_CONST_MEMBER_FUNCTION,
+// BOOST_PARAMETER_BASIC_FUNCTION_CALL_OPERATOR, and
+// BOOST_PARAMETER_BASIC_CONST_FUNCTION_CALL_OPERATOR.
+#define BOOST_PARAMETER_BASIC_MEMBER_FUNCTION_AUX(r, n, i, tag_ns, args, c) \
+ BOOST_PARAMETER_FUNCTION_HEAD(r, i, tag_ns, args, c) \
+ BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS(n, i, args, 1, c) \
+ BOOST_PARAMETER_FUNCTION_IMPL_HEAD(i, c) BOOST_PP_EXPR_IF(c, const)
/**/
-# if ! defined(BOOST_NO_SFINAE) && ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
-# define BOOST_PARAMETER_FUNCTION_FWD_MATCH_Z(z, name, parameters, n) \
- , typename boost::parameter::aux::match< \
- parameters, BOOST_PP_ENUM_PARAMS(n, ParameterArgumentType) \
- >::type = parameters()
-# else
-# define BOOST_PARAMETER_FUNCTION_FWD_MATCH_Z(z, name, parameters, n)
-# endif
-/**/
+#include <boost/parameter/aux_/preprocessor/impl/flatten.hpp>
-# define BOOST_PARAMETER_FUNCTION_PARAMETERS_NAME(base) \
- BOOST_PP_CAT( \
- boost_param_parameters_ \
- , BOOST_PP_CAT(__LINE__, BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base)) \
+// Expands to a Boost.Parameter-enabled constructor header. All arguments are
+// accessible via args and keywords only.
+#define BOOST_PARAMETER_CONSTRUCTOR(class_, base, tag_namespace, args) \
+ BOOST_PARAMETER_CONSTRUCTOR_AUX( \
+ class_, base, tag_namespace \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN(2, 2, 3, args) \
)
-
-// Produce a name for a result type metafunction for the function
-// named base
-# define BOOST_PARAMETER_FUNCTION_RESULT_NAME(base) \
- BOOST_PP_CAT( \
- boost_param_result_ \
- , BOOST_PP_CAT(__LINE__,BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base)) \
- )
-
-// Can't do boost_param_impl_ ## basee because base might start with an underscore
-// daniel: what? how is that relevant? the reason for using CAT() is to make sure
-// base is expanded. i'm not sure we need to here, but it's more stable to do it.
-# define BOOST_PARAMETER_IMPL(base) \
- BOOST_PP_CAT(boost_param_impl,BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base))
-
-# define BOOST_PARAMETER_FUNCTION_FWD_FUNCTION00(z, n, r, data, elem) \
- BOOST_PP_IF( \
- n \
- , BOOST_PARAMETER_FUNCTION_FWD_FUNCTION_TEMPLATE_Z, BOOST_PP_TUPLE_EAT(2) \
- )(z,n) \
- BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(BOOST_PP_TUPLE_ELEM(7,3,data)) \
- inline \
- BOOST_PP_EXPR_IF(n, typename) \
- BOOST_PARAMETER_FUNCTION_RESULT_NAME(BOOST_PP_TUPLE_ELEM(7,3,data))< \
- BOOST_PP_EXPR_IF(n, typename) \
- boost::parameter::aux::argument_pack< \
- BOOST_PARAMETER_FUNCTION_PARAMETERS_NAME(BOOST_PP_TUPLE_ELEM(7,3,data)) \
- BOOST_PP_COMMA_IF(n) \
- BOOST_PP_IF( \
- n, BOOST_PP_SEQ_ENUM, BOOST_PP_TUPLE_EAT(1) \
- )(elem) \
- >::type \
- >::type \
- BOOST_PARAMETER_MEMBER_FUNCTION_NAME(BOOST_PP_TUPLE_ELEM(7,3,data))( \
- BOOST_PP_IF( \
- n \
- , BOOST_PP_SEQ_FOR_EACH_I_R \
- , BOOST_PP_TUPLE_EAT(4) \
- )( \
- r \
- , BOOST_PARAMETER_FUNCTION_ARGUMENT \
- , ~ \
- , elem \
- ) \
- BOOST_PP_IF(n, BOOST_PARAMETER_FUNCTION_FWD_MATCH_Z, BOOST_PP_TUPLE_EAT(4))( \
- z \
- , BOOST_PP_TUPLE_ELEM(7,3,data) \
- , BOOST_PARAMETER_FUNCTION_PARAMETERS_NAME(BOOST_PP_TUPLE_ELEM(7,3,data)) \
- , n \
- ) \
- ) BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(7,4,data), const) \
- { \
- return BOOST_PARAMETER_IMPL(BOOST_PP_TUPLE_ELEM(7,3,data))( \
- BOOST_PARAMETER_FUNCTION_PARAMETERS_NAME(BOOST_PP_TUPLE_ELEM(7,3,data))()( \
- BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
- ) \
- ); \
- }
/**/
-# define BOOST_PARAMETER_FUNCTION_FWD_FUNCTION0(r, data, elem) \
- BOOST_PARAMETER_FUNCTION_FWD_FUNCTION00( \
- BOOST_PP_TUPLE_ELEM(7,0,data) \
- , BOOST_PP_TUPLE_ELEM(7,1,data) \
- , r \
- , data \
- , elem \
+// Expands to a Boost.Parameter-enabled function header. All arguments are
+// accessible via args and keywords only.
+#define BOOST_PARAMETER_BASIC_FUNCTION(result, name, tag_namespace, args) \
+ BOOST_PARAMETER_BASIC_FUNCTION_AUX( \
+ result, name, tag_namespace \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN(2, 2, 3, args) \
)
/**/
-# define BOOST_PARAMETER_FUNCTION_FWD_FUNCTION_ARITY_0(z, n, data) \
- BOOST_PARAMETER_FUNCTION_FWD_FUNCTION00( \
- z, n, BOOST_PP_DEDUCE_R() \
- , (z, n, BOOST_PP_TUPLE_REM(5) data) \
- , ~ \
+// Expands to a Boost.Parameter-enabled member function header. All arguments
+// are accessible via args and keywords only.
+#define BOOST_PARAMETER_BASIC_MEMBER_FUNCTION(result, name, tag_ns, args) \
+ BOOST_PARAMETER_BASIC_MEMBER_FUNCTION_AUX( \
+ result, name, name, tag_ns \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN(2, 2, 3, args), 0 \
)
/**/
-# define BOOST_PARAMETER_FUNCTION_FWD_FUNCTION_ARITY_N(z, n, data) \
- BOOST_PP_SEQ_FOR_EACH( \
- BOOST_PARAMETER_FUNCTION_FWD_FUNCTION0 \
- , (z, n, BOOST_PP_TUPLE_REM(5) data) \
- , BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
- BOOST_PARAMETER_FUNCTION_FWD_PRODUCT \
- , BOOST_PP_SEQ_FIRST_N( \
- n, BOOST_PP_TUPLE_ELEM(5,3,data) \
- ) \
- ) \
+// Expands to a Boost.Parameter-enabled const-qualified member function
+// header. All arguments are accessible via args and keywords only.
+#define BOOST_PARAMETER_BASIC_CONST_MEMBER_FUNCTION(r, name, tag_ns, args) \
+ BOOST_PARAMETER_BASIC_MEMBER_FUNCTION_AUX( \
+ r, name, name, tag_ns \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN(2, 2, 3, args), 1 \
)
/**/
-# define BOOST_PARAMETER_FUNCTION_FWD_FUNCTION(z, n, data) \
- BOOST_PP_IF( \
- n \
- , BOOST_PARAMETER_FUNCTION_FWD_FUNCTION_ARITY_N \
- , BOOST_PARAMETER_FUNCTION_FWD_FUNCTION_ARITY_0 \
- )(z,n,data) \
-/**/
-
-# define BOOST_PARAMETER_FUNCTION_FWD_FUNCTIONS0( \
- result,name,args,const_,combinations,range \
-) \
- BOOST_PP_REPEAT_FROM_TO( \
- BOOST_PP_TUPLE_ELEM(2,0,range), BOOST_PP_TUPLE_ELEM(2,1,range) \
- , BOOST_PARAMETER_FUNCTION_FWD_FUNCTION \
- , (result,name,const_,combinations,BOOST_PP_TUPLE_ELEM(2,1,range)) \
+// Expands to a Boost.Parameter-enabled function call operator header. All
+// arguments are accessible via args and keywords only.
+#define BOOST_PARAMETER_BASIC_FUNCTION_CALL_OPERATOR(result, tag_ns, args) \
+ BOOST_PARAMETER_BASIC_MEMBER_FUNCTION_AUX( \
+ result, operator(), operator, tag_ns \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN(2, 2, 3, args), 0 \
)
/**/
-# define BOOST_PARAMETER_FUNCTION_FWD_FUNCTIONS(result,name,args, const_, combinations) \
- BOOST_PARAMETER_FUNCTION_FWD_FUNCTIONS0( \
- result, name, args, const_, combinations, BOOST_PARAMETER_ARITY_RANGE(args) \
+// Expands to a Boost.Parameter-enabled const-qualified function call
+// operator header. All arguments are accessible via args and keywords only.
+#define BOOST_PARAMETER_BASIC_CONST_FUNCTION_CALL_OPERATOR(r, tag_ns, args) \
+ BOOST_PARAMETER_BASIC_MEMBER_FUNCTION_AUX( \
+ r, operator(), operator, tag_ns \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN(2, 2, 3, args), 1 \
)
/**/
-// Builds boost::parameter::parameters<> specialization
-# define BOOST_PARAMETER_FUNCTION_PARAMETERS_QUALIFIER_optional(tag) \
- optional<tag
-
-# define BOOST_PARAMETER_FUNCTION_PARAMETERS_QUALIFIER_required(tag) \
- required<tag
-
-# define BOOST_PARAMETER_FUNCTION_PARAMETERS_QUALIFIER_deduced_optional(tag) \
- optional<boost::parameter::deduced<tag>
-
-# define BOOST_PARAMETER_FUNCTION_PARAMETERS_QUALIFIER_deduced_required(tag) \
- required<boost::parameter::deduced<tag>
+#include <boost/parameter/aux_/preprocessor/impl/function_dispatch_layer.hpp>
-# if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-
-# define BOOST_PARAMETER_FUNCTION_PARAMETERS_M(r,tag_namespace,i,elem) \
- BOOST_PP_COMMA_IF(i) \
- boost::parameter::BOOST_PP_CAT( \
- BOOST_PARAMETER_FUNCTION_PARAMETERS_QUALIFIER_ \
- , BOOST_PARAMETER_FN_ARG_QUALIFIER(elem) \
- )( \
- tag_namespace::BOOST_PARAMETER_FUNCTION_KEYWORD( \
- BOOST_PARAMETER_FN_ARG_KEYWORD(elem) \
- ) \
- ) \
- , typename boost::parameter::aux::unwrap_predicate< \
- void BOOST_PARAMETER_FN_ARG_PRED(elem) \
- >::type \
- >
-# elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-# define BOOST_PARAMETER_FUNCTION_PARAMETERS_M(r,tag_namespace,i,elem) \
- BOOST_PP_COMMA_IF(i) \
- boost::parameter::BOOST_PP_CAT( \
- BOOST_PARAMETER_FUNCTION_PARAMETERS_QUALIFIER_ \
- , BOOST_PARAMETER_FN_ARG_QUALIFIER(elem) \
- )( \
- tag_namespace::BOOST_PARAMETER_FUNCTION_KEYWORD( \
- BOOST_PARAMETER_FN_ARG_KEYWORD(elem) \
- ) \
- ) \
- , boost::mpl::always<boost::mpl::true_> \
- >
-# endif
-
-# define BOOST_PARAMETER_FUNCTION_PARAMETERS(tag_namespace, base, args) \
- template <class BoostParameterDummy> \
- struct BOOST_PP_CAT( \
- BOOST_PP_CAT(boost_param_params_, __LINE__) \
- , BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base) \
- ) : boost::parameter::parameters< \
- BOOST_PP_SEQ_FOR_EACH_I( \
- BOOST_PARAMETER_FUNCTION_PARAMETERS_M, tag_namespace, args \
- ) \
- > \
- {}; \
- \
- typedef BOOST_PP_CAT( \
- BOOST_PP_CAT(boost_param_params_, __LINE__) \
- , BOOST_PARAMETER_MEMBER_FUNCTION_NAME(base) \
- )<int>
-
-// Defines result type metafunction
-# define BOOST_PARAMETER_FUNCTION_RESULT_ARG(z, _, i, x) \
- BOOST_PP_COMMA_IF(i) class BOOST_PP_TUPLE_ELEM(3,1,x)
-/**/
-
-# define BOOST_PARAMETER_FUNCTION_RESULT_(result, name, args) \
- template <class Args> \
- struct BOOST_PARAMETER_FUNCTION_RESULT_NAME(name) \
- { \
- typedef typename BOOST_PARAMETER_PARENTHESIZED_TYPE(result) type; \
- };
-
-// Defines implementation function
-# define BOOST_PARAMETER_FUNCTION_IMPL_HEAD(name) \
- template <class Args> \
- typename BOOST_PARAMETER_FUNCTION_RESULT_NAME(name)< \
- Args \
- >::type BOOST_PARAMETER_IMPL(name)(Args const& args)
-
-# define BOOST_PARAMETER_FUNCTION_IMPL_FWD(name) \
- BOOST_PARAMETER_FUNCTION_IMPL_HEAD(name);
-/**/
-
-# define BOOST_PARAMETER_FUNCTION_SPLIT_ARG_required(state, arg) \
- ( \
- BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(4, 0, state)) \
- , BOOST_PP_SEQ_PUSH_BACK(BOOST_PP_TUPLE_ELEM(4, 1, state), arg) \
- , BOOST_PP_TUPLE_ELEM(4, 2, state) \
- , BOOST_PP_TUPLE_ELEM(4, 3, state) \
- )
-
-# define BOOST_PARAMETER_FUNCTION_SPLIT_ARG_deduced_required(state, arg) \
- BOOST_PARAMETER_FUNCTION_SPLIT_ARG_required(state, arg)
-
-# define BOOST_PARAMETER_FUNCTION_SPLIT_ARG_optional(state, arg) \
- ( \
- BOOST_PP_TUPLE_ELEM(4, 0, state) \
- , BOOST_PP_TUPLE_ELEM(4, 1, state) \
- , BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(4, 2, state)) \
- , BOOST_PP_SEQ_PUSH_BACK(BOOST_PP_TUPLE_ELEM(4, 3, state), arg) \
- )
-
-# define BOOST_PARAMETER_FUNCTION_SPLIT_ARG_deduced_optional(state, arg) \
- BOOST_PARAMETER_FUNCTION_SPLIT_ARG_optional(state, arg)
-
-# define BOOST_PARAMETER_FUNCTION_SPLIT_ARG(s, state, arg) \
- BOOST_PP_CAT( \
- BOOST_PARAMETER_FUNCTION_SPLIT_ARG_ \
- , BOOST_PARAMETER_FN_ARG_QUALIFIER(arg) \
- )(state, arg)
-
-// Returns (required_count, required, optional_count, optionals) tuple
-# define BOOST_PARAMETER_FUNCTION_SPLIT_ARGS(args) \
- BOOST_PP_SEQ_FOLD_LEFT( \
- BOOST_PARAMETER_FUNCTION_SPLIT_ARG \
- , (0,BOOST_PP_SEQ_NIL, 0,BOOST_PP_SEQ_NIL) \
- , args \
- )
-
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_ARG_NAME(keyword) \
- BOOST_PP_CAT(BOOST_PP_CAT(keyword,_),type)
-
-// Helpers used as parameters to BOOST_PARAMETER_FUNCTION_DEFAULT_ARGUMENTS.
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_TEMPLATE_ARG(r, _, arg) \
- , class BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_ARG_NAME( \
- BOOST_PARAMETER_FN_ARG_KEYWORD(arg) \
- )
-
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_ARG(r, _, arg) \
- , BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_ARG_NAME( \
- BOOST_PARAMETER_FN_ARG_KEYWORD(arg) \
- )& BOOST_PARAMETER_FN_ARG_KEYWORD(arg)
-
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_PARAMETER(r, _, arg) \
- , BOOST_PARAMETER_FN_ARG_KEYWORD(arg)
-
-// Produces a name for the dispatch functions.
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_NAME(name) \
- BOOST_PP_CAT( \
- boost_param_default_ \
- , BOOST_PP_CAT(__LINE__, BOOST_PARAMETER_MEMBER_FUNCTION_NAME(name)) \
- )
-
-// Helper macro used below to produce lists based on the keyword argument
-// names. macro is applied to every element. n is the number of
-// optional arguments that should be included.
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_ARGUMENTS(macro, n, split_args) \
- BOOST_PP_SEQ_FOR_EACH( \
- macro \
- , ~ \
- , BOOST_PP_TUPLE_ELEM(4,1,split_args) \
- ) \
- BOOST_PP_SEQ_FOR_EACH( \
- macro \
- , ~ \
- , BOOST_PP_SEQ_FIRST_N( \
- BOOST_PP_SUB(BOOST_PP_TUPLE_ELEM(4,2,split_args), n) \
- , BOOST_PP_TUPLE_ELEM(4,3,split_args) \
- ) \
- )
-
-// Generates a keyword | default expression.
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_EVAL_DEFAULT(arg, tag_namespace) \
- boost::parameter::keyword< \
- tag_namespace::BOOST_PARAMETER_FN_ARG_KEYWORD(arg) \
- >::instance | boost::parameter::aux::use_default_tag()
-
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_GET_ARG(arg, tag_ns) \
- BOOST_PARAMETER_FUNCTION_CAST( \
- args[ \
- BOOST_PARAMETER_FUNCTION_DEFAULT_EVAL_DEFAULT( \
- arg, tag_ns \
- ) \
- ] \
- , BOOST_PARAMETER_FN_ARG_PRED(arg) \
- , Args \
- )
-
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_BODY(name, n, split_args, tag_namespace) \
- { \
- return BOOST_PARAMETER_FUNCTION_DEFAULT_NAME(name)( \
- (ResultType(*)())0 \
- , args \
- , 0L \
- BOOST_PARAMETER_FUNCTION_DEFAULT_ARGUMENTS( \
- BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_PARAMETER \
- , n \
- , split_args \
- ) \
- , BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_GET_ARG( \
- BOOST_PP_SEQ_ELEM( \
- BOOST_PP_SUB(BOOST_PP_TUPLE_ELEM(4,2,split_args), n) \
- , BOOST_PP_TUPLE_ELEM(4,3,split_args) \
- ) \
- , tag_namespace \
- ) \
- ); \
- }
-
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_EVAL_ACTUAL_DEFAULT(arg) \
- BOOST_PARAMETER_FUNCTION_CAST( \
- boost::parameter::aux::as_lvalue(BOOST_PARAMETER_FN_ARG_DEFAULT(arg), 0L) \
- , BOOST_PARAMETER_FN_ARG_PRED(arg) \
- , Args \
- )
-
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_EVAL_DEFAULT_BODY(name, n, split_args, tag_ns, const_) \
- template < \
- class ResultType \
- , class Args \
- BOOST_PARAMETER_FUNCTION_DEFAULT_ARGUMENTS( \
- BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_TEMPLATE_ARG \
- , BOOST_PP_INC(n) \
- , split_args \
- ) \
- > \
- BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(name) \
- ResultType BOOST_PARAMETER_FUNCTION_DEFAULT_NAME(name)( \
- ResultType(*)() \
- , Args const& args \
- , long \
- BOOST_PARAMETER_FUNCTION_DEFAULT_ARGUMENTS( \
- BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_ARG \
- , BOOST_PP_INC(n) \
- , split_args \
- ) \
- , boost::parameter::aux::use_default_tag \
- ) BOOST_PP_EXPR_IF(const_, const) \
- { \
- return BOOST_PARAMETER_FUNCTION_DEFAULT_NAME(name)( \
- (ResultType(*)())0 \
- , args \
- , 0L \
- BOOST_PARAMETER_FUNCTION_DEFAULT_ARGUMENTS( \
- BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_PARAMETER \
- , BOOST_PP_INC(n) \
- , split_args \
- ) \
- , BOOST_PARAMETER_FUNCTION_DEFAULT_EVAL_ACTUAL_DEFAULT( \
- BOOST_PP_SEQ_ELEM( \
- BOOST_PP_SUB(BOOST_PP_TUPLE_ELEM(4,2,split_args), BOOST_PP_INC(n)) \
- , BOOST_PP_TUPLE_ELEM(4,3,split_args) \
- ) \
- ) \
- ); \
- }
-
-// Produces a forwarding layer in the default evaluation machine.
-//
-// data is a tuple:
-//
-// (name, split_args)
-//
-// Where name is the base name of the function, and split_args is a tuple:
-//
-// (required_count, required_args, optional_count, required_args)
-//
-
-
-// defines the actual function body for BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION below.
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION0(z, n, data) \
- template < \
- class ResultType \
- , class Args \
- BOOST_PARAMETER_FUNCTION_DEFAULT_ARGUMENTS( \
- BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_TEMPLATE_ARG \
- , n \
- , BOOST_PP_TUPLE_ELEM(5,1,data) \
- ) \
- > \
- BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(BOOST_PP_TUPLE_ELEM(5,0,data)) \
- ResultType BOOST_PARAMETER_FUNCTION_DEFAULT_NAME(BOOST_PP_TUPLE_ELEM(5,0,data))( \
- ResultType(*)() \
- , Args const& args \
- , int \
- BOOST_PARAMETER_FUNCTION_DEFAULT_ARGUMENTS( \
- BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_ARG \
- , n \
- , BOOST_PP_TUPLE_ELEM(5,1,data) \
- ) \
- ) BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(5,2,data), const) \
- BOOST_PP_IF( \
- n \
- , BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_BODY \
- , ; BOOST_PP_TUPLE_EAT(4) \
- )( \
- BOOST_PP_TUPLE_ELEM(5,0,data) \
- , n \
- , BOOST_PP_TUPLE_ELEM(5,1,data) \
- , BOOST_PP_TUPLE_ELEM(5,3,data) \
- )
-
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION(z, n, data) \
- BOOST_PP_IF( \
- BOOST_PP_AND( \
- BOOST_PP_NOT(n) \
- , BOOST_PP_TUPLE_ELEM(5,4,data) \
- ) \
- , BOOST_PP_TUPLE_EAT(3) \
- , BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION0 \
- )(z, n, data) \
- BOOST_PP_IF( \
- BOOST_PP_EQUAL(n, BOOST_PP_TUPLE_ELEM(4,2,BOOST_PP_TUPLE_ELEM(5,1,data))) \
- , BOOST_PP_TUPLE_EAT(5) \
- , BOOST_PARAMETER_FUNCTION_DEFAULT_EVAL_DEFAULT_BODY \
- )( \
- BOOST_PP_TUPLE_ELEM(5,0,data) \
- , n \
- , BOOST_PP_TUPLE_ELEM(5,1,data) \
- , BOOST_PP_TUPLE_ELEM(5,3,data) \
- , BOOST_PP_TUPLE_ELEM(5,2,data) \
- )
-
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_GET_ARG(r, tag_ns, arg) \
- , BOOST_PARAMETER_FUNCTION_CAST( \
- args[ \
- boost::parameter::keyword<tag_ns::BOOST_PARAMETER_FN_ARG_KEYWORD(arg)>::instance \
- ] \
- , BOOST_PARAMETER_FN_ARG_PRED(arg) \
- , Args \
- )
-
-// Generates the function template that recives a ArgumentPack, and then
-// goes on to call the layers of overloads generated by
-// BOOST_PARAMETER_FUNCTION_DEFAULT_LAYER.
-# define BOOST_PARAMETER_FUNCTION_INITIAL_DISPATCH_FUNCTION(name, split_args, const_, tag_ns) \
- template <class Args> \
- typename BOOST_PARAMETER_FUNCTION_RESULT_NAME(name)<Args>::type \
- BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(name) \
- BOOST_PARAMETER_IMPL(name)(Args const& args) BOOST_PP_EXPR_IF(const_, const) \
- { \
- return BOOST_PARAMETER_FUNCTION_DEFAULT_NAME(name)( \
- (typename BOOST_PARAMETER_FUNCTION_RESULT_NAME(name)<Args>::type(*)())0 \
- , args \
- , 0L \
- \
- BOOST_PP_SEQ_FOR_EACH( \
- BOOST_PARAMETER_FUNCTION_DEFAULT_GET_ARG \
- , tag_ns \
- , BOOST_PP_TUPLE_ELEM(4,1,split_args) \
- ) \
- \
- ); \
- }
-
-// Helper for BOOST_PARAMETER_FUNCTION_DEFAULT_LAYER below.
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_LAYER_AUX( \
- name, split_args, skip_fwd_decl, const_, tag_namespace \
- ) \
- BOOST_PP_REPEAT_FROM_TO( \
- 0 \
- , BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(4, 2, split_args)) \
- , BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION \
- , (name, split_args, const_, tag_namespace, skip_fwd_decl) \
- ) \
- \
- BOOST_PARAMETER_FUNCTION_INITIAL_DISPATCH_FUNCTION(name, split_args, const_, tag_namespace) \
-\
- template < \
- class ResultType \
- , class Args \
- BOOST_PARAMETER_FUNCTION_DEFAULT_ARGUMENTS( \
- BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_TEMPLATE_ARG \
- , 0 \
- , split_args \
- ) \
- > \
- BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(name) \
- ResultType BOOST_PARAMETER_FUNCTION_DEFAULT_NAME(name)( \
- ResultType(*)() \
- , Args const& \
- , int \
- BOOST_PARAMETER_FUNCTION_DEFAULT_ARGUMENTS( \
- BOOST_PARAMETER_FUNCTION_DEFAULT_FUNCTION_ARG \
- , 0 \
- , split_args \
- ) \
- ) BOOST_PP_EXPR_IF(const_, const)
-
-// Generates a bunch of forwarding functions that each extract
-// one more argument.
-# define BOOST_PARAMETER_FUNCTION_DEFAULT_LAYER(name, args, skip_fwd_decl, const_, tag_ns) \
- BOOST_PARAMETER_FUNCTION_DEFAULT_LAYER_AUX( \
- name, BOOST_PARAMETER_FUNCTION_SPLIT_ARGS(args), skip_fwd_decl, const_, tag_ns \
- )
-/**/
-
-// Defines the result metafunction and the parameters specialization.
-# define BOOST_PARAMETER_FUNCTION_HEAD(result, name, tag_namespace, args) \
- BOOST_PARAMETER_FUNCTION_RESULT_(result, name, args) \
- \
- BOOST_PARAMETER_FUNCTION_PARAMETERS(tag_namespace, name, args) \
- BOOST_PARAMETER_FUNCTION_PARAMETERS_NAME(name); \
-
-// Helper for BOOST_PARAMETER_FUNCTION below.
-# define BOOST_PARAMETER_FUNCTION_AUX(result, name, tag_namespace, args) \
- BOOST_PARAMETER_FUNCTION_HEAD(result, name, tag_namespace, args) \
- BOOST_PARAMETER_FUNCTION_IMPL_HEAD(name); \
-\
- BOOST_PARAMETER_FUNCTION_FWD_FUNCTIONS( \
- result, name, args, 0 \
- , BOOST_PARAMETER_FUNCTION_FWD_COMBINATIONS(args) \
- ) \
- \
- BOOST_PARAMETER_FUNCTION_DEFAULT_LAYER(name, args, 0, 0, tag_namespace)
-
-// Defines a Boost.Parameter enabled function with the new syntax.
-# define BOOST_PARAMETER_FUNCTION(result, name, tag_namespace, args) \
- BOOST_PARAMETER_FUNCTION_AUX( \
- result, name, tag_namespace \
- , BOOST_PARAMETER_FLATTEN(3, 2, 3, args) \
- ) \
-/**/
-
-// Defines a Boost.Parameter enabled function.
-# define BOOST_PARAMETER_BASIC_FUNCTION_AUX(result, name, tag_namespace, args) \
- BOOST_PARAMETER_FUNCTION_HEAD(result, name, tag_namespace, args) \
- \
- BOOST_PARAMETER_FUNCTION_IMPL_FWD(name) \
- \
- BOOST_PARAMETER_FUNCTION_FWD_FUNCTIONS( \
- result, name, args, 0 \
- , BOOST_PARAMETER_FUNCTION_FWD_COMBINATIONS(args) \
- ) \
- \
- BOOST_PARAMETER_FUNCTION_IMPL_HEAD(name)
-
-# define BOOST_PARAMETER_BASIC_FUNCTION(result, name, tag_namespace, args) \
- BOOST_PARAMETER_BASIC_FUNCTION_AUX( \
- result, name, tag_namespace \
- , BOOST_PARAMETER_FLATTEN(2, 2, 3, args) \
- ) \
-/**/
-
-// Defines a Boost.Parameter enabled member function.
-# define BOOST_PARAMETER_BASIC_MEMBER_FUNCTION_AUX(result, name, tag_namespace, args, const_) \
- BOOST_PARAMETER_FUNCTION_HEAD(result, name, tag_namespace, args) \
- \
- BOOST_PARAMETER_FUNCTION_FWD_FUNCTIONS( \
- result, name, args, const_ \
- , BOOST_PARAMETER_FUNCTION_FWD_COMBINATIONS(args) \
- ) \
- \
- BOOST_PARAMETER_FUNCTION_IMPL_HEAD(name) BOOST_PP_EXPR_IF(const_, const) \
-/**/
-
-# define BOOST_PARAMETER_BASIC_MEMBER_FUNCTION(result, name, tag_namespace, args) \
- BOOST_PARAMETER_BASIC_MEMBER_FUNCTION_AUX( \
- result, name, tag_namespace \
- , BOOST_PARAMETER_FLATTEN(2, 2, 3, args) \
- , 0 \
+// Helper macro for BOOST_PARAMETER_FUNCTION.
+#define BOOST_PARAMETER_FUNCTION_AUX(result, name, tag_ns, args) \
+ BOOST_PARAMETER_FUNCTION_HEAD(result, name, tag_ns, args, 0) \
+ BOOST_PARAMETER_FUNCTION_IMPL_HEAD(name, 0); \
+ BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS(name, name, args, 0, 0) \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_LAYER( \
+ 1, (name, BOOST_PARAMETER_FUNCTION_SPLIT_ARGS(args), 0, 0, tag_ns) \
)
/**/
-# define BOOST_PARAMETER_BASIC_CONST_MEMBER_FUNCTION(result, name, tag_namespace, args) \
- BOOST_PARAMETER_BASIC_MEMBER_FUNCTION_AUX( \
- result, name, tag_namespace \
- , BOOST_PARAMETER_FLATTEN(2, 2, 3, args) \
- , 1 \
- )
-/**/
-
-
-
-# define BOOST_PARAMETER_MEMBER_FUNCTION_AUX(result, name, tag_namespace, const_, args) \
- BOOST_PARAMETER_FUNCTION_HEAD(result, name, tag_namespace, args) \
-\
- BOOST_PARAMETER_FUNCTION_FWD_FUNCTIONS( \
- result, name, args, const_ \
- , BOOST_PARAMETER_FUNCTION_FWD_COMBINATIONS(args) \
- ) \
- \
- BOOST_PARAMETER_FUNCTION_DEFAULT_LAYER(name, args, 1, const_, tag_namespace)
-
-// Defines a Boost.Parameter enabled function with the new syntax.
-# define BOOST_PARAMETER_MEMBER_FUNCTION(result, name, tag_namespace, args) \
- BOOST_PARAMETER_MEMBER_FUNCTION_AUX( \
- result, name, tag_namespace, 0 \
- , BOOST_PARAMETER_FLATTEN(3, 2, 3, args) \
- ) \
-/**/
-
-# define BOOST_PARAMETER_CONST_MEMBER_FUNCTION(result, name, tag_namespace, args) \
- BOOST_PARAMETER_MEMBER_FUNCTION_AUX( \
- result, name, tag_namespace, 1 \
- , BOOST_PARAMETER_FLATTEN(3, 2, 3, args) \
- ) \
-/**/
-
-// Defines a Boost.Parameter enabled constructor.
-
-# define BOOST_PARAMETER_FUNCTION_ARGUMENT(r, _, i, elem) \
- BOOST_PP_COMMA_IF(i) elem& BOOST_PP_CAT(a, i)
-/**/
-
-# define BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTOR00(z, n, r, data, elem) \
- BOOST_PP_IF( \
- n \
- , BOOST_PARAMETER_FUNCTION_FWD_FUNCTION_TEMPLATE_Z, BOOST_PP_TUPLE_EAT(2) \
- )(z, n) \
- BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(n,1), explicit) \
- BOOST_PP_TUPLE_ELEM(6,2,data)( \
- BOOST_PP_IF( \
- n \
- , BOOST_PP_SEQ_FOR_EACH_I_R \
- , BOOST_PP_TUPLE_EAT(4) \
- )( \
- r \
- , BOOST_PARAMETER_FUNCTION_ARGUMENT \
- , ~ \
- , elem \
- ) \
- BOOST_PP_IF(n, BOOST_PARAMETER_FUNCTION_FWD_MATCH_Z, BOOST_PP_TUPLE_EAT(4))( \
- z \
- , BOOST_PP_TUPLE_ELEM(6,3,data) \
- , BOOST_PP_CAT(constructor_parameters, __LINE__) \
- , n \
- ) \
- ) \
- : BOOST_PARAMETER_PARENTHESIZED_TYPE(BOOST_PP_TUPLE_ELEM(6,3,data)) ( \
- BOOST_PP_CAT(constructor_parameters, __LINE__)()( \
- BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
- ) \
- ) \
- {}
-/**/
-
-# define BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTOR0(r, data, elem) \
- BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTOR00( \
- BOOST_PP_TUPLE_ELEM(6,0,data) \
- , BOOST_PP_TUPLE_ELEM(6,1,data) \
- , r \
- , data \
- , elem \
+// Expands to a Boost.Parameter-enabled function header. All arguments are
+// accessible via args and keywords, as well as by name.
+#define BOOST_PARAMETER_FUNCTION(result, name, tag_namespace, args) \
+ BOOST_PARAMETER_FUNCTION_AUX( \
+ result, name, tag_namespace \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN(3, 2, 3, args) \
)
/**/
-# define BOOST_PARAMETER_FUNCTION_FWD_PRODUCT(r, product) \
- (product)
-/**/
+#include <boost/preprocessor/control/if.hpp>
-# define BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTOR_ARITY_0(z, n, data) \
- BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTOR00( \
- z, n, BOOST_PP_DEDUCE_R() \
- , (z, n, BOOST_PP_TUPLE_REM(4) data) \
- , ~ \
+// Helper macro for BOOST_PARAMETER_MEMBER_FUNCTION
+// BOOST_PARAMETER_CONST_MEMBER_FUNCTION,
+// BOOST_PARAMETER_FUNCTION_CALL_OPERATOR, and
+// BOOST_PARAMETER_CONST_FUNCTION_CALL_OPERATOR.
+#define BOOST_PARAMETER_MEMBER_FUNCTION_AUX(r, name, impl, tag_ns, c, args) \
+ BOOST_PARAMETER_FUNCTION_HEAD(r, impl, tag_ns, args, c) \
+ BOOST_PARAMETER_FUNCTION_FORWARD_OVERLOADS(name, impl, args, 1, c) \
+ BOOST_PARAMETER_FUNCTION_DISPATCH_LAYER( \
+ 0, ( \
+ impl \
+ , BOOST_PARAMETER_FUNCTION_SPLIT_ARGS(args) \
+ , BOOST_PP_IF( \
+ BOOST_PARAMETER_MEMBER_FUNCTION_IS_STATIC(impl) \
+ , 0 \
+ , 1 \
+ ) \
+ , c \
+ , tag_ns \
+ ) \
)
/**/
-# define BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTOR_ARITY_N(z, n, data) \
- BOOST_PP_SEQ_FOR_EACH( \
- BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTOR0 \
- , (z, n, BOOST_PP_TUPLE_REM(4) data) \
- , BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
- BOOST_PARAMETER_FUNCTION_FWD_PRODUCT \
- , BOOST_PP_SEQ_FIRST_N( \
- n, BOOST_PP_TUPLE_ELEM(4,2,data) \
- ) \
- ) \
+// Expands to a Boost.Parameter-enabled member function header. All
+// arguments are accessible via args and keywords, as well as by name.
+#define BOOST_PARAMETER_MEMBER_FUNCTION(result, name, tag_ns, args) \
+ BOOST_PARAMETER_MEMBER_FUNCTION_AUX( \
+ result, name, name, tag_ns, 0 \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN(3, 2, 3, args) \
)
/**/
-# define BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTOR(z, n, data) \
- BOOST_PP_IF( \
- n \
- , BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTOR_ARITY_N \
- , BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTOR_ARITY_0 \
- )(z,n,data) \
-/**/
-
-# define BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTORS0(class_,base,args,combinations,range) \
- BOOST_PP_REPEAT_FROM_TO( \
- BOOST_PP_TUPLE_ELEM(2,0,range), BOOST_PP_TUPLE_ELEM(2,1,range) \
- , BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTOR \
- , (class_,base,combinations,BOOST_PP_TUPLE_ELEM(2,1,range)) \
+// Expands to a Boost.Parameter-enabled const-qualified member function
+// header. All arguments are accessible via args and keywords, as well as
+// by name.
+#define BOOST_PARAMETER_CONST_MEMBER_FUNCTION(result, name, tag_ns, args) \
+ BOOST_PARAMETER_MEMBER_FUNCTION_AUX( \
+ result, name, name, tag_ns, 1 \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN(3, 2, 3, args) \
)
/**/
-# define BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTORS(class_,base,args,combinations) \
- BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTORS0( \
- class_, base, args, combinations, BOOST_PARAMETER_ARITY_RANGE(args) \
+// Expands to a Boost.Parameter-enabled function call operator header. All
+// arguments are accessible via args and keywords, as well as by name.
+#define BOOST_PARAMETER_FUNCTION_CALL_OPERATOR(result, tag_ns, args) \
+ BOOST_PARAMETER_MEMBER_FUNCTION_AUX( \
+ result, operator(), operator, tag_ns, 0 \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN(3, 2, 3, args) \
)
/**/
-# define BOOST_PARAMETER_CONSTRUCTOR_AUX(class_, base, tag_namespace, args) \
- BOOST_PARAMETER_FUNCTION_PARAMETERS(tag_namespace, ctor, args) \
- BOOST_PP_CAT(constructor_parameters, __LINE__); \
-\
- BOOST_PARAMETER_FUNCTION_FWD_CONSTRUCTORS( \
- class_, base, args \
- , BOOST_PARAMETER_FUNCTION_FWD_COMBINATIONS(args) \
- ) \
-/**/
-
-# define BOOST_PARAMETER_CONSTRUCTOR(class_, base, tag_namespace, args) \
- BOOST_PARAMETER_CONSTRUCTOR_AUX( \
- class_, base, tag_namespace \
- , BOOST_PARAMETER_FLATTEN(2, 2, 3, args) \
+// Expands to a Boost.Parameter-enabled const-qualified function call operator
+// header. All arguments are accessible via args and keywords, as well as
+// by name.
+#define BOOST_PARAMETER_CONST_FUNCTION_CALL_OPERATOR(result, tag_ns, args) \
+ BOOST_PARAMETER_MEMBER_FUNCTION_AUX( \
+ result, operator(), operator, tag_ns, 1 \
+ , BOOST_PARAMETER_AUX_PP_FLATTEN(3, 2, 3, args) \
)
/**/
-# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
-# define BOOST_PARAMETER_FUNCTION_FWD_COMBINATION(r, _, i, elem) \
- (BOOST_PP_IF( \
- BOOST_PARAMETER_FUNCTION_IS_KEYWORD_QUALIFIER( \
- BOOST_PARAMETER_FN_ARG_NAME(elem) \
- ) \
- , (const ParameterArgumentType ## i)(ParameterArgumentType ## i) \
- , (const ParameterArgumentType ## i) \
- ))
-// No partial ordering. This feature doesn't work.
-# else
-# define BOOST_PARAMETER_FUNCTION_FWD_COMBINATION(r, _, i, elem) \
- (BOOST_PP_IF( \
- BOOST_PARAMETER_FUNCTION_IS_KEYWORD_QUALIFIER( \
- BOOST_PARAMETER_FN_ARG_NAME(elem) \
- ) \
- , (ParameterArgumentType ## i) \
- , (const ParameterArgumentType ## i) \
- ))
-# endif
-
-# define BOOST_PARAMETER_FUNCTION_FWD_COMBINATIONS(args) \
- BOOST_PP_SEQ_FOR_EACH_I(BOOST_PARAMETER_FUNCTION_FWD_COMBINATION, ~, args)
-
-#endif // BOOST_PARAMETER_PREPROCESSOR_060206_HPP
+#endif // include guard
diff --git a/boost/parameter/preprocessor_no_spec.hpp b/boost/parameter/preprocessor_no_spec.hpp
new file mode 100644
index 0000000000..a40b89c485
--- /dev/null
+++ b/boost/parameter/preprocessor_no_spec.hpp
@@ -0,0 +1,74 @@
+// Copyright Cromwell D. Enage 2019.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_PREPROCESSOR_NO_SPEC_HPP
+#define BOOST_PARAMETER_PREPROCESSOR_NO_SPEC_HPP
+
+#include <boost/parameter/aux_/preprocessor/impl/function_name.hpp>
+#include <boost/parameter/aux_/preprocessor/impl/no_spec_overloads.hpp>
+
+// Exapnds to a variadic function header that is enabled if and only if all
+// its arguments are tagged arguments. All arguments are accessible via args
+// and keywords only.
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION(result, name) \
+ BOOST_PARAMETER_NO_SPEC_FUNCTION_HEAD(result, name, 0) \
+ BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_HEAD(name, 0); \
+ BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD(name, name, 0, 0) \
+ BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_HEAD(name, 0)
+/**/
+
+#include <boost/preprocessor/control/expr_if.hpp>
+#include <boost/preprocessor/control/if.hpp>
+
+// Helper macro for BOOST_PARAMETER_NO_SPEC_MEMBER_FUNCTION,
+// BOOST_PARAMETER_NO_SPEC_CONST_MEMBER_FUNCTION,
+// BOOST_PARAMETER_NO_SPEC_FUNCTION_CALL_OPERATOR, and
+// and BOOST_PARAMETER_NO_SPEC_CONST_FUNCTION_CALL_OPERATOR.
+#define BOOST_PARAMETER_NO_SPEC_MEMBER_FUNCTION_AUX(result, name, impl, c) \
+ BOOST_PARAMETER_NO_SPEC_FUNCTION_HEAD(result, impl, c) \
+ BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD( \
+ name \
+ , impl \
+ , BOOST_PP_IF(BOOST_PARAMETER_MEMBER_FUNCTION_IS_STATIC(impl), 0, 1) \
+ , c \
+ ) \
+ BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_HEAD(impl, c) \
+ BOOST_PP_EXPR_IF(c, const)
+/**/
+
+// Exapnds to a variadic member function header that is enabled if and only if
+// all its arguments are tagged arguments. All arguments are accessible via
+// args and keywords only.
+#define BOOST_PARAMETER_NO_SPEC_MEMBER_FUNCTION(result, name) \
+ BOOST_PARAMETER_NO_SPEC_MEMBER_FUNCTION_AUX(result, name, name, 0)
+/**/
+
+// Exapnds to a const-qualified variadic member function header that is
+// enabled if and only if all its arguments are tagged arguments. All
+// arguments are accessible via args and keywords only.
+#define BOOST_PARAMETER_NO_SPEC_CONST_MEMBER_FUNCTION(result, name) \
+ BOOST_PARAMETER_NO_SPEC_MEMBER_FUNCTION_AUX(result, name, name, 1)
+/**/
+
+// Exapnds to a variadic function call operator header that is enabled if and
+// only if all its arguments are tagged arguments. All arguments are
+// accessible via args and keywords only.
+#define BOOST_PARAMETER_NO_SPEC_FUNCTION_CALL_OPERATOR(result) \
+ BOOST_PARAMETER_NO_SPEC_MEMBER_FUNCTION_AUX( \
+ result, operator(), operator, 0 \
+ )
+/**/
+
+// Exapnds to a const-qualified variadic function call operator header that is
+// enabled if and only if all its arguments are tagged arguments. All
+// arguments are accessible via args and keywords only.
+#define BOOST_PARAMETER_NO_SPEC_CONST_FUNCTION_CALL_OPERATOR(result) \
+ BOOST_PARAMETER_NO_SPEC_MEMBER_FUNCTION_AUX( \
+ result, operator(), operator, 1 \
+ )
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/required.hpp b/boost/parameter/required.hpp
new file mode 100644
index 0000000000..cd08405f28
--- /dev/null
+++ b/boost/parameter/required.hpp
@@ -0,0 +1,66 @@
+// Copyright David Abrahams, Daniel Wallin 2003.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PARAMETER_REQUIRED_HPP
+#define BOOST_PARAMETER_REQUIRED_HPP
+
+#include <boost/parameter/aux_/use_default.hpp>
+
+namespace boost { namespace parameter {
+
+ // This metafunction can be used to describe the treatment of particular
+ // named parameters for the purposes of overload elimination with SFINAE,
+ // by placing specializations in the parameters<...> list. In order for
+ // a treated function to participate in overload resolution:
+ //
+ // - all keyword tags wrapped in required<...> must have a matching
+ // actual argument
+ //
+ // - The actual argument type matched by every keyword tag
+ // associated with a predicate must satisfy that predicate
+ template <
+ typename Tag
+ , typename Predicate = ::boost::parameter::aux::use_default
+ >
+ struct required
+ {
+ typedef Tag key_type;
+ typedef Predicate predicate;
+ };
+}}
+
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#else
+#include <boost/mpl/bool.hpp>
+#endif
+
+namespace boost { namespace parameter { namespace aux {
+
+ template <typename T>
+ struct is_required
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_false
+#else
+ : ::boost::mpl::false_
+#endif
+ {
+ };
+
+ template <typename Tag, typename Predicate>
+ struct is_required< ::boost::parameter::required<Tag,Predicate> >
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mp11::mp_true
+#else
+ : ::boost::mpl::true_
+#endif
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // include guard
+
diff --git a/boost/parameter/template_keyword.hpp b/boost/parameter/template_keyword.hpp
new file mode 100644
index 0000000000..ef2aa58d14
--- /dev/null
+++ b/boost/parameter/template_keyword.hpp
@@ -0,0 +1,87 @@
+// Copyright Daniel Wallin 2006.
+// Copyright Cromwell D. Enage 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_PARAMETER_TEMPLATE_KEYWORD_HPP
+#define BOOST_PARAMETER_TEMPLATE_KEYWORD_HPP
+
+#include <boost/parameter/aux_/template_keyword.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/type_traits/add_lvalue_reference.hpp>
+#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/is_array.hpp>
+#endif
+
+namespace boost { namespace parameter {
+
+ template <typename Tag, typename T>
+ struct template_keyword : ::boost::parameter::aux::template_keyword_base
+ {
+ typedef Tag key_type;
+ typedef T value_type;
+
+ // reference is needed for two reasons:
+ //
+ // 1. It is used in the body of arg_list<...>
+ //
+ // 2. It is the result of binding<...>, which we mistakenly told
+ // people to use instead of value_type<...> to access named
+ // template parameters
+ //
+ // It used to be that reference == value_type, but that broke when
+ // the argument was a function or array type, because various
+ // arg_list functions return reference.
+ //
+ // Simply making reference == value_type& would break all the
+ // legacy code that uses binding<...> to access named template
+ // parameters. -- David Abrahams
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using reference = typename ::boost::mp11::mp_eval_if<
+ ::boost::mp11::mp_if<
+ ::std::is_function<value_type>
+ , ::boost::mp11::mp_true
+ , ::std::is_array<value_type>
+ >
+ , ::std::add_lvalue_reference<value_type>
+ , ::boost::mp11::mp_identity
+ , value_type
+ >::type;
+#else
+ typedef typename ::boost::mpl::eval_if<
+ typename ::boost::mpl::if_<
+ ::boost::is_function<value_type>
+ , ::boost::mpl::true_
+ , ::boost::is_array<value_type>
+ >::type
+ , ::boost::add_lvalue_reference<value_type>
+ , ::boost::mpl::identity<value_type>
+ >::type reference;
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ };
+}} // namespace boost::parameter
+
+#define BOOST_PARAMETER_TEMPLATE_KEYWORD(name) \
+ namespace tag \
+ { \
+ struct name; \
+ } \
+ template <typename T> \
+ struct name : ::boost::parameter::template_keyword<tag::name,T> \
+ { \
+ };
+/**/
+
+#endif // include guard
+
diff --git a/boost/parameter/value_type.hpp b/boost/parameter/value_type.hpp
index a323dcf37c..1b0ad354c9 100644
--- a/boost/parameter/value_type.hpp
+++ b/boost/parameter/value_type.hpp
@@ -1,82 +1,164 @@
-// Copyright Daniel Wallin 2006. Use, modification and distribution is
-// subject to the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright Daniel Wallin 2006.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARAMETER_VALUE_TYPE_060921_HPP
-# define BOOST_PARAMETER_VALUE_TYPE_060921_HPP
+#define BOOST_PARAMETER_VALUE_TYPE_060921_HPP
-# include <boost/mpl/apply.hpp>
-# include <boost/mpl/assert.hpp>
-# include <boost/mpl/and.hpp>
-# include <boost/parameter/aux_/result_of0.hpp>
-# include <boost/parameter/aux_/void.hpp>
-# include <boost/type_traits/is_same.hpp>
+#include <boost/parameter/aux_/void.hpp>
+#include <boost/parameter/config.hpp>
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#endif
namespace boost { namespace parameter {
-// A metafunction that, given an argument pack, returns the type of
-// the parameter identified by the given keyword. If no such
-// parameter has been specified, returns Default
-
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-template <class Parameters, class Keyword, class Default>
-struct value_type0
-{
- typedef typename mpl::apply_wrap3<
- typename Parameters::binding,Keyword,Default,mpl::false_
- >::type type;
-
- BOOST_MPL_ASSERT_NOT((
- mpl::and_<
- is_same<Default, void_>
- , is_same<type, void_>
- >
- ));
-};
-# endif
-
-template <class Parameters, class Keyword, class Default = void_>
-struct value_type
-{
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- typedef typename mpl::eval_if<
- mpl::is_placeholder<Parameters>
- , mpl::identity<int>
- , value_type0<Parameters,Keyword,Default>
- >::type type;
-# else
- typedef typename mpl::apply_wrap3<
- typename Parameters::binding,Keyword,Default,mpl::false_
- >::type type;
-
- BOOST_MPL_ASSERT_NOT((
- mpl::and_<
- is_same<Default, void_>
- , is_same<type, void_>
+ // A metafunction that, given an argument pack, returns the value type
+ // of the parameter identified by the given keyword. If no such parameter
+ // has been specified, returns Default
+
+ template <typename Parameters, typename Keyword, typename Default>
+ struct value_type0
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_apply_q<
+ typename Parameters::binding
+ , ::boost::mp11::mp_list<Keyword,Default,::boost::mp11::mp_false>
+ >;
+
+ static_assert(
+ ::boost::mp11::mp_if<
+ ::std::is_same<Default,::boost::parameter::void_>
+ , ::boost::mp11::mp_if<
+ ::std::is_same<type,::boost::parameter::void_>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ , ::boost::mp11::mp_true
+ >::value
+ , "required parameters must not result in void_ type"
+ );
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ typedef typename ::boost::mpl::apply_wrap3<
+ typename Parameters::binding
+ , Keyword
+ , Default
+ , ::boost::mpl::false_
+ >::type type;
+
+ BOOST_MPL_ASSERT((
+ typename ::boost::mpl::eval_if<
+ ::boost::is_same<Default,::boost::parameter::void_>
+ , ::boost::mpl::if_<
+ ::boost::is_same<type,::boost::parameter::void_>
+ , ::boost::mpl::false_
+ , ::boost::mpl::true_
+ >
+ , ::boost::mpl::true_
+ >::type
+ ));
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ };
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename Placeholder, typename Keyword, typename Default>
+ struct value_type1
+ {
+ using type = ::boost::mp11::mp_apply_q<
+ Placeholder
+ , ::boost::mp11::mp_list<Keyword,Default,::boost::mp11::mp_false>
+ >;
+
+ static_assert(
+ ::boost::mp11::mp_if<
+ ::std::is_same<Default,::boost::parameter::void_>
+ , ::boost::mp11::mp_if<
+ ::std::is_same<type,::boost::parameter::void_>
+ , ::boost::mp11::mp_false
+ , ::boost::mp11::mp_true
+ >
+ , ::boost::mp11::mp_true
+ >::value
+ , "required parameters must not result in void_ type"
+ );
+ };
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+}} // namespace boost::parameter
+
+#include <boost/parameter/aux_/is_placeholder.hpp>
+
+namespace boost { namespace parameter {
+
+ template <
+ typename Parameters
+ , typename Keyword
+ , typename Default = ::boost::parameter::void_
+ >
+ struct value_type
+#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ : ::boost::mpl::eval_if<
+ ::boost::parameter::aux::is_mpl_placeholder<Parameters>
+ , ::boost::mpl::identity<int>
+ , ::boost::parameter::value_type0<Parameters,Keyword,Default>
>
- ));
-# endif
-
- BOOST_MPL_AUX_LAMBDA_SUPPORT(3,value_type,(Parameters,Keyword,Default))
-};
-
-// A metafunction that, given an argument pack, returns the type of
-// the parameter identified by the given keyword. If no such
-// parameter has been specified, returns the type returned by invoking
-// DefaultFn
-template <class Parameters, class Keyword, class DefaultFn>
-struct lazy_value_type
-{
- typedef typename mpl::apply_wrap3<
- typename Parameters::binding
- , Keyword
- , typename aux::result_of0<DefaultFn>::type
- , mpl::false_
- >::type type;
-};
+#endif
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = typename ::boost::mp11::mp_if<
+ ::boost::parameter::aux::is_mpl_placeholder<Parameters>
+ , ::boost::mp11::mp_identity<int>
+ , ::boost::mp11::mp_if<
+ ::boost::parameter::aux::is_mp11_placeholder<Parameters>
+ , ::boost::parameter::value_type1<Parameters,Keyword,Default>
+ , ::boost::parameter::value_type0<Parameters,Keyword,Default>
+ >
+ >::type;
+#endif
+ };
+}} // namespace boost::parameter
+
+#include <boost/parameter/aux_/result_of0.hpp>
+namespace boost { namespace parameter {
+ // A metafunction that, given an argument pack, returns the value type
+ // of the parameter identified by the given keyword. If no such parameter
+ // has been specified, returns the type returned by invoking DefaultFn
+ template <typename Parameters, typename Keyword, typename DefaultFn>
+ struct lazy_value_type
+ {
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ using type = ::boost::mp11::mp_apply_q<
+ typename Parameters::binding
+ , ::boost::mp11::mp_list<
+ Keyword
+ , typename ::boost::parameter::aux::result_of0<DefaultFn>::type
+ , ::boost::mp11::mp_false
+ >
+ >;
+#else
+ typedef typename ::boost::mpl::apply_wrap3<
+ typename Parameters::binding
+ , Keyword
+ , typename ::boost::parameter::aux::result_of0<DefaultFn>::type
+ , ::boost::mpl::false_
+ >::type type;
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ };
}} // namespace boost::parameter
-#endif // BOOST_PARAMETER_VALUE_TYPE_060921_HPP
+#endif // include guard
diff --git a/boost/pending/bucket_sorter.hpp b/boost/pending/bucket_sorter.hpp
index 8b7926d2df..97c26b2626 100644
--- a/boost/pending/bucket_sorter.hpp
+++ b/boost/pending/bucket_sorter.hpp
@@ -19,34 +19,37 @@
#include <vector>
#include <cassert>
#include <boost/limits.hpp>
+#include <boost/concept/assert.hpp>
+#include <boost/property_map/property_map.hpp>
namespace boost {
- template <class BucketType, class ValueType, class Bucket,
+ template <class BucketType, class ValueType, class Bucket,
class ValueIndexMap>
class bucket_sorter {
+ BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<ValueIndexMap, ValueType> ));
public:
typedef BucketType bucket_type;
typedef ValueType value_type;
typedef typename std::vector<value_type>::size_type size_type;
-
- bucket_sorter(size_type _length, bucket_type _max_bucket,
- const Bucket& _bucket = Bucket(),
- const ValueIndexMap& _id = ValueIndexMap())
+
+ bucket_sorter(size_type _length, bucket_type _max_bucket,
+ const Bucket& _bucket = Bucket(),
+ const ValueIndexMap& _id = ValueIndexMap())
: head(_max_bucket, invalid_value()),
- next(_length, invalid_value()),
+ next(_length, invalid_value()),
prev(_length, invalid_value()),
id_to_value(_length),
bucket(_bucket), id(_id) { }
-
+
void remove(const value_type& x) {
const size_type i = get(id, x);
const size_type& next_node = next[i];
const size_type& prev_node = prev[i];
-
- //check if i is the end of the bucket list
+
+ //check if i is the end of the bucket list
if ( next_node != invalid_value() )
- prev[next_node] = prev_node;
+ prev[next_node] = prev_node;
//check if i is the begin of the bucket list
if ( prev_node != invalid_value() )
next[prev_node] = next_node;
@@ -58,21 +61,21 @@ namespace boost {
id_to_value[get(id, x)] = x;
(*this)[bucket[x]].push(x);
}
-
+
void update(const value_type& x) {
remove(x);
(*this)[bucket[x]].push(x);
}
- // private:
+ // private:
// with KCC, the nested stack class is having access problems
// despite the friend decl.
static size_type invalid_value() {
return (std::numeric_limits<size_type>::max)();
}
-
+
typedef typename std::vector<size_type>::iterator Iter;
typedef typename std::vector<value_type>::iterator IndexValueMap;
-
+
public:
friend class stack;
@@ -86,7 +89,7 @@ namespace boost {
// constructor of the ValueIndexMap is not required if not used.
stack(bucket_type _bucket_id, Iter h, Iter n, Iter p, IndexValueMap v)
: bucket_id(_bucket_id), head(h), next(n), prev(p), value(v) {}
-
+
void push(const value_type& x) {
const size_type new_head = get(id, x);
const size_type current = head[bucket_id];
@@ -114,7 +117,7 @@ namespace boost {
IndexValueMap value;
ValueIndexMap id;
};
-
+
stack operator[](const bucket_type& i) {
assert(i < head.size());
return stack(i, head.begin(), next.begin(), prev.begin(),
@@ -128,7 +131,7 @@ namespace boost {
Bucket bucket;
ValueIndexMap id;
};
-
+
}
#endif
diff --git a/boost/pending/property_serialize.hpp b/boost/pending/property_serialize.hpp
index a3cf9f6c3b..06cf2927a1 100644
--- a/boost/pending/property_serialize.hpp
+++ b/boost/pending/property_serialize.hpp
@@ -7,11 +7,7 @@
#define BOOST_PROPERTY_SERIALIZE_HPP
#include <boost/pending/property.hpp>
-#ifdef BOOST_GRAPH_USE_MPI
-#include <boost/mpi/datatype.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>
-#endif // BOOST_GRAPH_USE_MPI
-
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/nvp.hpp>
@@ -29,7 +25,26 @@ namespace boost {
}
#ifdef BOOST_GRAPH_USE_MPI
+
+// Setting the serialization properties of boost::property<> and
+// boost::no_property to is_bitwise_serializable, object_serializable,
+// track_never only when BOOST_GRAPH_USE_MPI is defined is dubious.
+//
+// This changes the serialization format of these classes, and hence
+// of boost::adjacency_list, depending on whether BOOST_GRAPH_USE_MPI
+// is defined.
+//
+// These serialization properties should probably be set in either case.
+//
+// Unfortunately, doing that now will change the serialization format
+// of boost::adjacency_list in the non-MPI case, and could potentially
+// break software that reads files serialized with an older release.
+
namespace mpi {
+
+ // forward declaration, to avoid including mpi
+ template<typename T> struct is_mpi_datatype;
+
template<typename Tag, typename T, typename Base>
struct is_mpi_datatype<property<Tag, T, Base> >
: mpl::and_<is_mpi_datatype<T>,
diff --git a/boost/pending/relaxed_heap.hpp b/boost/pending/relaxed_heap.hpp
index 8be4484735..f7523eb1b2 100644
--- a/boost/pending/relaxed_heap.hpp
+++ b/boost/pending/relaxed_heap.hpp
@@ -6,9 +6,13 @@
// Authors: Douglas Gregor
// Andrew Lumsdaine
+#warning "Use of relaxed_heap is depreciated; please use the standard heap functions."
#ifndef BOOST_RELAXED_HEAP_HEADER
#define BOOST_RELAXED_HEAP_HEADER
+#include <boost/config/header_deprecated.hpp>
+BOOST_HEADER_DEPRECATED("the standard heap functions")
+
#include <functional>
#include <boost/property_map/property_map.hpp>
#include <boost/optional.hpp>
diff --git a/boost/poly_collection/detail/stride_iterator.hpp b/boost/poly_collection/detail/stride_iterator.hpp
index 66ecdf07a0..ec0de42790 100644
--- a/boost/poly_collection/detail/stride_iterator.hpp
+++ b/boost/poly_collection/detail/stride_iterator.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+/* Copyright 2016-2019 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)
@@ -13,6 +13,7 @@
#pragma once
#endif
+#include <boost/detail/workaround.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <type_traits>
@@ -72,6 +73,23 @@ public:
explicit stride_iterator(DerivedValue* x)noexcept:
p{x},stride_{sizeof(DerivedValue)}{}
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION,>=40900)||\
+ BOOST_WORKAROUND(BOOST_CLANG,>=1)&&\
+ (__clang_major__>3 || __clang_major__==3 && __clang_minor__ >= 8)
+/* https://github.com/boostorg/poly_collection/issues/15 */
+
+#define BOOST_POLY_COLLECTION_NO_SANITIZE
+
+/* UBSan seems not to be supported in some environments */
+#if defined(BOOST_GCC_VERSION)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wattributes"
+#elif defined(BOOST_CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wattributes"
+#endif
+#endif
+
template<
typename DerivedValue,
typename std::enable_if<
@@ -79,9 +97,22 @@ public:
(!std::is_const<Value>::value||std::is_const<DerivedValue>::value)
>::type* =nullptr
>
+#if defined(BOOST_POLY_COLLECTION_NO_SANITIZE)
+ __attribute__((no_sanitize("undefined")))
+#endif
explicit operator DerivedValue*()const noexcept
{return static_cast<DerivedValue*>(p);}
+#if defined(BOOST_POLY_COLLECTION_NO_SANITIZE)
+#if defined(BOOST_GCC_VERSION)
+#pragma GCC diagnostic pop
+#elif defined(BOOST_CLANG)
+#pragma clang diagnostic pop
+#endif
+
+#undef BOOST_POLY_COLLECTION_NO_SANITIZE
+#endif
+
std::size_t stride()const noexcept{return stride_;}
private:
diff --git a/boost/polygon/detail/voronoi_ctypes.hpp b/boost/polygon/detail/voronoi_ctypes.hpp
index a2ea9ffd63..078d935183 100644
--- a/boost/polygon/detail/voronoi_ctypes.hpp
+++ b/boost/polygon/detail/voronoi_ctypes.hpp
@@ -12,6 +12,7 @@
#include <boost/cstdint.hpp>
+#include <algorithm>
#include <cmath>
#include <cstring>
#include <utility>
diff --git a/boost/process.hpp b/boost/process.hpp
index e0ad694358..1bf59516f4 100644
--- a/boost/process.hpp
+++ b/boost/process.hpp
@@ -30,6 +30,7 @@
#include <boost/process/error.hpp>
#include <boost/process/exe.hpp>
#include <boost/process/group.hpp>
+#include <boost/process/handles.hpp>
#include <boost/process/io.hpp>
#include <boost/process/pipe.hpp>
#include <boost/process/shell.hpp>
diff --git a/boost/process/detail/child_decl.hpp b/boost/process/detail/child_decl.hpp
index c30a7aa6f1..6b782140b1 100644
--- a/boost/process/detail/child_decl.hpp
+++ b/boost/process/detail/child_decl.hpp
@@ -145,11 +145,12 @@ public:
bool running(std::error_code & ec) noexcept
{
- if (valid() && !_exited())
+ ec.clear();
+ if (valid() && !_exited() && !ec)
{
int exit_code = 0;
auto res = boost::process::detail::api::is_running(_child_handle, exit_code, ec);
- if (!res && !_exited())
+ if (!ec && !res && !_exited())
_exit_status->store(exit_code);
return res;
@@ -159,10 +160,11 @@ public:
void terminate(std::error_code & ec) noexcept
{
- if (valid() && running(ec))
+ if (valid() && running(ec) && !ec)
boost::process::detail::api::terminate(_child_handle, ec);
- _terminated = true;
+ if (!ec)
+ _terminated = true;
}
void wait(std::error_code & ec) noexcept
@@ -171,7 +173,8 @@ public:
{
int exit_code = 0;
boost::process::detail::api::wait(_child_handle, exit_code, ec);
- _exit_status->store(exit_code);
+ if (!ec)
+ _exit_status->store(exit_code);
}
}
@@ -188,7 +191,7 @@ public:
{
int exit_code = 0;
auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time, ec);
- if (!b)
+ if (!b || ec)
return false;
_exit_status->store(exit_code);
}
diff --git a/boost/process/detail/posix/async_in.hpp b/boost/process/detail/posix/async_in.hpp
index 5033d3e6f8..513163816d 100644
--- a/boost/process/detail/posix/async_in.hpp
+++ b/boost/process/detail/posix/async_in.hpp
@@ -16,13 +16,16 @@
#include <boost/process/async_pipe.hpp>
#include <memory>
#include <future>
+#include <boost/process/detail/used_handles.hpp>
+#include <array>
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_context
+ ::boost::process::detail::posix::require_io_context,
+ ::boost::process::detail::uses_handles
{
Buffer & buf;
@@ -33,6 +36,7 @@ struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
fut = promise->get_future(); return std::move(*this);
}
+
std::shared_ptr<boost::process::async_pipe> pipe;
async_in_buffer(Buffer & buf) : buf(buf)
@@ -76,9 +80,19 @@ struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
template<typename Executor>
void on_setup(Executor & exec)
{
- pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
+ if (!pipe)
+ pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
}
+ std::array<int, 3> get_used_handles()
+ {
+ if (pipe)
+ return {STDIN_FILENO, pipe->native_source(), pipe->native_sink()};
+ else //if pipe is not constructed, limit_ds is invoked before -> this also means on_exec_setup gets invoked before.
+ return {STDIN_FILENO, STDIN_FILENO, STDIN_FILENO};
+ }
+
+
template <typename Executor>
void on_exec_setup(Executor &exec)
{
diff --git a/boost/process/detail/posix/async_out.hpp b/boost/process/detail/posix/async_out.hpp
index 983779ec26..bbf4179081 100644
--- a/boost/process/detail/posix/async_out.hpp
+++ b/boost/process/detail/posix/async_out.hpp
@@ -19,6 +19,8 @@
#include <memory>
#include <exception>
#include <future>
+#include <array>
+#include <boost/process/detail/used_handles.hpp>
namespace boost { namespace process { namespace detail { namespace posix {
@@ -45,12 +47,24 @@ inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::in
template<int p1, int p2, typename Buffer>
struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext,
- ::boost::process::detail::posix::require_io_context
+ ::boost::process::detail::posix::require_io_context,
+ ::boost::process::detail::uses_handles
{
Buffer & buf;
std::shared_ptr<boost::process::async_pipe> pipe;
+ std::array<int, 4> get_used_handles()
+ {
+ const auto pp1 = p1 != -1 ? p1 : p2;
+ const auto pp2 = p2 != -1 ? p2 : p1;
+
+ if (pipe)
+ return {pipe->native_source(), pipe->native_sink(), pp1, pp2};
+ else //if pipe is not constructed, limit_ds is invoked before -> this also means on_exec_setup gets invoked before.
+ return {pp1, pp2, pp1, pp2};
+ }
+
async_out_buffer(Buffer & buf) : buf(buf)
{
diff --git a/boost/process/detail/posix/basic_pipe.hpp b/boost/process/detail/posix/basic_pipe.hpp
index 14d140f1cc..92db99d982 100644
--- a/boost/process/detail/posix/basic_pipe.hpp
+++ b/boost/process/detail/posix/basic_pipe.hpp
@@ -97,7 +97,7 @@ public:
return read_len;
}
- bool is_open()
+ bool is_open() const
{
return (_source != -1) ||
(_sink != -1);
diff --git a/boost/process/detail/posix/close_in.hpp b/boost/process/detail/posix/close_in.hpp
index 74cffd6729..708f1ac44b 100644
--- a/boost/process/detail/posix/close_in.hpp
+++ b/boost/process/detail/posix/close_in.hpp
@@ -12,10 +12,11 @@
#include <boost/process/detail/posix/handler.hpp>
+#include <boost/process/detail/used_handles.hpp>
namespace boost { namespace process { namespace detail { namespace posix {
-struct close_in : handler_base_ext
+struct close_in : handler_base_ext, ::boost::process::detail::uses_handles
{
template <class Executor>
void on_exec_setup(Executor &e) const
@@ -23,6 +24,9 @@ struct close_in : handler_base_ext
if (::close(STDIN_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "close() failed");
}
+
+ int get_used_handles() {return STDIN_FILENO;}
+
};
}}}}
diff --git a/boost/process/detail/posix/close_out.hpp b/boost/process/detail/posix/close_out.hpp
index f3659f5544..83d46327c7 100644
--- a/boost/process/detail/posix/close_out.hpp
+++ b/boost/process/detail/posix/close_out.hpp
@@ -10,8 +10,9 @@
#ifndef BOOST_PROCESS_DETAIL_POSIX_CLOSE_OUT_HPP
#define BOOST_PROCESS_DETAIL_POSIX_CLOSE_OUT_HPP
-
+#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/posix/handler.hpp>
+#include <array>
namespace boost { namespace process { namespace detail { namespace posix {
@@ -20,6 +21,8 @@ struct close_out : handler_base_ext
{
template <class Executor>
inline void on_exec_setup(Executor &e) const;
+
+ std::array<int, 2> get_used_handles() {return {p1 != -1 ? p1 : p2, p2 != -1 ? p2 : p1};}
};
template<>
diff --git a/boost/process/detail/posix/executor.hpp b/boost/process/detail/posix/executor.hpp
index 1390a58ee6..c031689b98 100644
--- a/boost/process/detail/posix/executor.hpp
+++ b/boost/process/detail/posix/executor.hpp
@@ -22,47 +22,12 @@
#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
{
@@ -295,15 +260,41 @@ class executor
return;
//EAGAIN not yet forked, EINTR interrupted, i.e. try again
else if ((err != EAGAIN ) && (err != EINTR))
- {
- ::close(source);
set_error(std::error_code(err, std::system_category()), "Error read pipe");
- }
}
- ::close(source);
set_error(ec, std::move(msg));
}
+ std::string prepare_cmd_style_fn; //buffer
+
+ inline void prepare_cmd_style() //this does what execvpe does - but we execute it in the father process, to avoid allocations.
+ {
+ //use my own implementation
+ prepare_cmd_style_fn = exe;
+ if ((prepare_cmd_style_fn.find('/') == std::string::npos) && ::access(prepare_cmd_style_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 + "/" + exe;
+ if (!::access(p.c_str(), X_OK))
+ {
+ prepare_cmd_style_fn = p;
+ break;
+ }
+ }
+ }
+ }
+ exe = prepare_cmd_style_fn.c_str();
+ }
std::error_code _ec;
std::string _msg;
@@ -342,6 +333,8 @@ child executor<Sequence>::invoke(boost::mpl::true_, boost::mpl::false_) //ignore
boost::fusion::for_each(seq, call_on_setup(*this));
if (_ec)
return child();
+ if (cmd_style)
+ prepare_cmd_style();
this->pid = ::fork();
if (pid == -1)
@@ -353,10 +346,7 @@ child executor<Sequence>::invoke(boost::mpl::true_, boost::mpl::false_) //ignore
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);
+ ::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);
@@ -372,71 +362,85 @@ child executor<Sequence>::invoke(boost::mpl::true_, boost::mpl::false_) //ignore
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)
{
- auto err = ::boost::process::detail::get_last_error();
- ::close(p[0]);
- ::close(p[1]);
- set_error(err, "fcntl(2) failed");
- return child();
- }
- _ec.clear();
- boost::fusion::for_each(seq, call_on_setup(*this));
+ struct pipe_guard
+ {
+ int p[2];
+ pipe_guard() : p{-1,-1} {}
- if (_ec)
- {
- boost::fusion::for_each(seq, call_on_error(*this, _ec));
- return child();
- }
+ ~pipe_guard()
+ {
+ if (p[0] != -1)
+ ::close(p[0]);
+ if (p[1] != -1)
+ ::close(p[1]);
+ }
+ } p{};
- 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));
+ if (::pipe(p.p) == -1)
+ {
+ set_error(::boost::process::detail::get_last_error(), "pipe(2) failed");
+ return child();
+ }
+ if (::fcntl(p.p[1], F_SETFD, FD_CLOEXEC) == -1)
+ {
+ auto err = ::boost::process::detail::get_last_error();
+ set_error(err, "fcntl(2) failed");//this might throw, so we need to be sure our pipe is safe.
+ return child();
+ }
+ _ec.clear();
+ boost::fusion::for_each(seq, call_on_setup(*this));
- return child();
- }
- else if (pid == 0)
- {
- _pipe_sink = p[1];
- ::close(p[0]);
+ if (_ec)
+ {
+ boost::fusion::for_each(seq, call_on_error(*this, _ec));
+ return child();
+ }
- 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));
+ prepare_cmd_style();
- _write_error(p[1]);
+ 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.p[1];
+ ::close(p.p[0]);
- _exit(EXIT_FAILURE);
- return child();
- }
+ boost::fusion::for_each(seq, call_on_exec_setup(*this));
+ ::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));
- child c(child_handle(pid), exit_status);
+ _write_error(_pipe_sink);
+ ::close(p.p[1]);
+
+ _exit(EXIT_FAILURE);
+ return child();
+ }
- ::close(p[1]);
- _read_error(p[0]);
+ ::close(p.p[1]);
+ p.p[1] = -1;
+ _read_error(p.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));
+
+ child c(child_handle(pid), exit_status);
+
+ boost::fusion::for_each(seq, call_on_success(*this));
if (_ec)
{
@@ -489,6 +493,8 @@ child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::true_)
return child();
}
_ec.clear();
+ if (cmd_style)
+ this->prepare_cmd_style();
this->pid = ::vfork();
if (pid == -1)
@@ -504,10 +510,7 @@ child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::true_)
{
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);
+ ::execve(exe, cmd_line, env);
_ec = boost::process::detail::get_last_error();
_msg = "execve failed";
diff --git a/boost/process/detail/posix/fd.hpp b/boost/process/detail/posix/fd.hpp
index 51790c3237..bd5f153d37 100644
--- a/boost/process/detail/posix/fd.hpp
+++ b/boost/process/detail/posix/fd.hpp
@@ -12,11 +12,13 @@
#include <boost/process/detail/posix/handler.hpp>
#include <unistd.h>
+#include <boost/process/detail/used_handles.hpp>
+#include <array>
namespace boost { namespace process { namespace detail { namespace posix {
-struct close_fd_ : handler_base_ext
+struct close_fd_ : handler_base_ext, ::boost::process::detail::uses_handles
{
close_fd_(int fd) : fd_(fd) {}
@@ -27,12 +29,15 @@ struct close_fd_ : handler_base_ext
e.set_error(::boost::process::detail::get_last_error(), "close() failed");
}
+ int get_used_handles() {return fd_;}
+
+
private:
int fd_;
};
template <class Range>
-struct close_fds_ : handler_base_ext
+struct close_fds_ : handler_base_ext, ::boost::process::detail::uses_handles
{
public:
close_fds_(const Range &fds) : fds_(fds) {}
@@ -48,6 +53,8 @@ public:
}
}
+ Range& get_used_handles() {return fds_;}
+
private:
Range fds_;
};
@@ -55,7 +62,7 @@ private:
template <class FileDescriptor>
-struct bind_fd_ : handler_base_ext
+struct bind_fd_ : handler_base_ext, ::boost::process::detail::uses_handles
{
public:
bind_fd_(int id, const FileDescriptor &fd) : id_(id), fd_(fd) {}
@@ -67,6 +74,9 @@ public:
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
}
+ std::array<int, 2> get_used_handles() {return {id_, fd_};}
+
+
private:
int id_;
FileDescriptor fd_;
diff --git a/boost/process/detail/posix/file_in.hpp b/boost/process/detail/posix/file_in.hpp
index 7ddd71684b..799f92c3e4 100644
--- a/boost/process/detail/posix/file_in.hpp
+++ b/boost/process/detail/posix/file_in.hpp
@@ -13,16 +13,22 @@
#include <boost/process/pipe.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
+#include <boost/process/detail/used_handles.hpp>
#include <cstdio>
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
-struct file_in : handler_base_ext
+struct file_in : handler_base_ext, ::boost::process::detail::uses_handles
{
file_descriptor file;
int handle = file.handle();
+ std::array<int, 2> get_used_handles()
+ {
+ return {STDIN_FILENO, handle};
+ }
+
template<typename T>
file_in(T&& t) : file(std::forward<T>(t)) {}
file_in(FILE * f) : handle(fileno(f)) {}
diff --git a/boost/process/detail/posix/file_out.hpp b/boost/process/detail/posix/file_out.hpp
index 8e3d4eb716..ce32b32635 100644
--- a/boost/process/detail/posix/file_out.hpp
+++ b/boost/process/detail/posix/file_out.hpp
@@ -13,12 +13,13 @@
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
-
+#include <boost/process/detail/used_handles.hpp>
#include <unistd.h>
+
namespace boost { namespace process { namespace detail { namespace posix {
template<int p1, int p2>
-struct file_out : handler_base_ext
+struct file_out : handler_base_ext, ::boost::process::detail::uses_handles
{
file_descriptor file;
int handle = file.handle();
@@ -27,6 +28,13 @@ struct file_out : handler_base_ext
file_out(T&& t) : file(std::forward<T>(t), file_descriptor::write), handle(file.handle()) {}
file_out(FILE * f) : handle(fileno(f)) {}
+ std::array<int, 3> get_used_handles()
+ {
+ const auto pp1 = p1 != -1 ? p1 : p2;
+ const auto pp2 = p2 != -1 ? p2 : p1;
+
+ return {handle, pp1, pp2};
+ }
template <typename Executor>
void on_exec_setup(Executor &e) const;
diff --git a/boost/process/detail/posix/handles.hpp b/boost/process/detail/posix/handles.hpp
new file mode 100644
index 0000000000..1572f05933
--- /dev/null
+++ b/boost/process/detail/posix/handles.hpp
@@ -0,0 +1,146 @@
+// Copyright (c) 2019 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_HANDLES_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_HANDLES_HPP_
+
+#include <vector>
+#include <system_error>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <algorithm>
+#include <boost/process/detail/posix/handler.hpp>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+
+using native_handle_type = int;
+
+inline std::vector<native_handle_type> get_handles(std::error_code & ec)
+{
+ std::vector<native_handle_type> res;
+
+ std::unique_ptr<DIR, void(*)(DIR*)> dir{::opendir("/dev/fd"), +[](DIR* p){::closedir(p);}};
+ if (!dir)
+ {
+ ec = ::boost::process::detail::get_last_error();
+ return {};
+ }
+ else
+ ec.clear();
+
+ auto my_fd = ::dirfd(dir.get());
+
+ struct ::dirent * ent_p;
+
+ while ((ent_p = readdir(dir.get())) != nullptr)
+ {
+ if (ent_p->d_name[0] == '.')
+ continue;
+
+ const auto conv = std::atoi(ent_p->d_name);
+ if (conv == 0 && (ent_p->d_name[0] != '0' && ent_p->d_name[1] != '\0'))
+ continue;
+
+ if (conv == my_fd)
+ continue;
+
+ res.push_back(conv);
+ }
+ return res;
+}
+
+inline std::vector<native_handle_type> get_handles()
+{
+ std::error_code ec;
+
+ auto res = get_handles(ec);
+ if (ec)
+ boost::process::detail::throw_error(ec, "open_dir(\"/dev/fd\") failed");
+
+ return res;
+}
+
+
+inline bool is_stream_handle(native_handle_type handle, std::error_code & ec)
+{
+ struct ::stat stat_;
+
+ if (::fstat(handle, &stat_) != 0)
+ {
+ ec = ::boost::process::detail::get_last_error();
+ }
+ else
+ ec.clear();
+
+ return S_ISCHR (stat_.st_mode) //This macro returns non-zero if the file is a character special file (a device like a terminal).
+ || S_ISBLK (stat_.st_mode) // This macro returns non-zero if the file is a block special file (a device like a disk).
+ || S_ISREG (stat_.st_mode) // This macro returns non-zero if the file is a regular file.
+ || S_ISFIFO (stat_.st_mode) // This macro returns non-zero if the file is a FIFO special file, or a pipe. See section 15. Pipes and FIFOs.
+ || S_ISSOCK (stat_.st_mode) ;// This macro returns non-zero if the file is a socket. See section 16. Sockets.;
+}
+
+
+inline bool is_stream_handle(native_handle_type handle)
+{
+ std::error_code ec;
+ auto res = is_stream_handle(handle, ec);
+ if (ec)
+ boost::process::detail::throw_error(ec, "fstat() failed");
+
+ return res;
+}
+
+struct limit_handles_ : handler_base_ext
+{
+ limit_handles_() {}
+ ~limit_handles_() {}
+ mutable std::vector<int> used_handles;
+
+ template<typename Executor>
+ void on_setup(Executor & exec) const
+ {
+ used_handles = get_used_handles(exec);
+ }
+
+ template<typename Executor>
+ void on_exec_setup(Executor & exec) const
+ {
+ auto dir = ::opendir("/dev/fd");
+ if (!dir)
+ {
+ exec.set_error(::boost::process::detail::get_last_error(), "opendir(\"/dev/fd\")");
+ return;
+ }
+
+ auto my_fd = ::dirfd(dir);
+ struct ::dirent * ent_p;
+
+ while ((ent_p = readdir(dir)) != nullptr)
+ {
+ if (ent_p->d_name[0] == '.')
+ continue;
+
+ const auto conv = std::atoi(ent_p->d_name);
+
+ if ((conv == my_fd) || (conv == -1))
+ continue;
+
+ if (std::find(used_handles.begin(), used_handles.end(), conv) != used_handles.end())
+ continue;
+
+ if (::close(conv) != 0)
+ {
+ exec.set_error(::boost::process::detail::get_last_error(), "close() failed");
+ return;
+ }
+ }
+ ::closedir(dir);
+ }
+};
+
+}}}}
+
+#endif //PROCESS_HANDLES_HPP
diff --git a/boost/process/detail/posix/null_in.hpp b/boost/process/detail/posix/null_in.hpp
index 33ced810b1..cf64a1dec3 100644
--- a/boost/process/detail/posix/null_in.hpp
+++ b/boost/process/detail/posix/null_in.hpp
@@ -14,13 +14,21 @@
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
#include <unistd.h>
+#include <boost/process/detail/used_handles.hpp>
+#include <array>
namespace boost { namespace process { namespace detail { namespace posix {
-struct null_in : handler_base_ext
+struct null_in : handler_base_ext, ::boost::process::detail::uses_handles
{
file_descriptor source{"/dev/null", file_descriptor::read};
+ std::array<int, 2> get_used_handles()
+ {
+ return {STDIN_FILENO, source.handle()};
+ }
+
+
public:
template <class Executor>
void on_exec_setup(Executor &e) const
diff --git a/boost/process/detail/posix/null_out.hpp b/boost/process/detail/posix/null_out.hpp
index 3874475f4d..b879ff54de 100644
--- a/boost/process/detail/posix/null_out.hpp
+++ b/boost/process/detail/posix/null_out.hpp
@@ -13,17 +13,27 @@
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/file_descriptor.hpp>
-
+#include <boost/process/detail/used_handles.hpp>
#include <unistd.h>
+#include <array>
+
namespace boost { namespace process { namespace detail { namespace posix {
template<int p1, int p2>
-struct null_out : handler_base_ext
+struct null_out : handler_base_ext, ::boost::process::detail::uses_handles
{
file_descriptor sink{"/dev/null", file_descriptor::write};
template <typename Executor>
void on_exec_setup(Executor &e) const;
+
+ std::array<int, 3> get_used_handles()
+ {
+ const auto pp1 = p1 != -1 ? p1 : p2;
+ const auto pp2 = p2 != -1 ? p2 : p1;
+
+ return {sink.handle(), pp1, pp2};
+ }
};
template<>
diff --git a/boost/process/detail/posix/pipe_in.hpp b/boost/process/detail/posix/pipe_in.hpp
index 18ca856573..da8b3838be 100644
--- a/boost/process/detail/posix/pipe_in.hpp
+++ b/boost/process/detail/posix/pipe_in.hpp
@@ -13,17 +13,23 @@
#include <boost/process/pipe.hpp>
#include <boost/process/detail/posix/handler.hpp>
#include <unistd.h>
-
+#include <boost/process/detail/used_handles.hpp>
+#include <array>
namespace boost { namespace process { namespace detail { namespace posix {
-struct pipe_in : handler_base_ext
+struct pipe_in : handler_base_ext, ::boost::process::detail::uses_handles
{
int source;
int sink; //opposite end
pipe_in(int sink, int source) : source(source), sink(sink) {}
+ std::array<int, 3> get_used_handles()
+ {
+ return {STDIN_FILENO, source, sink};
+ }
+
template<typename T>
pipe_in(T & p) : source(p.native_source()), sink(p.native_sink())
@@ -48,7 +54,9 @@ struct pipe_in : handler_base_ext
{
if (::dup2(source, STDIN_FILENO) == -1)
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- ::close(source);
+ if (source != STDIN_FILENO)
+ ::close(source);
+
::close(sink);
}
diff --git a/boost/process/detail/posix/pipe_out.hpp b/boost/process/detail/posix/pipe_out.hpp
index 9f7da9464b..d54cca4efa 100644
--- a/boost/process/detail/posix/pipe_out.hpp
+++ b/boost/process/detail/posix/pipe_out.hpp
@@ -52,8 +52,10 @@ 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);
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+
+ if (sink != STDOUT_FILENO)
+ ::close(sink);
::close(source);
}
@@ -63,7 +65,9 @@ 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);
+
+ if (sink != STDOUT_FILENO)
+ ::close(sink);
::close(source);
}
@@ -75,8 +79,8 @@ void pipe_out<1,2>::on_exec_setup(Executor &e) const
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);
+ if ((sink != STDOUT_FILENO) && (sink != STDERR_FILENO))
+ ::close(sink);
}
class async_pipe;
diff --git a/boost/process/detail/posix/terminate.hpp b/boost/process/detail/posix/terminate.hpp
index 84024a5b34..e1e5f33fec 100644
--- a/boost/process/detail/posix/terminate.hpp
+++ b/boost/process/detail/posix/terminate.hpp
@@ -27,7 +27,7 @@ inline void terminate(const child_handle &p, std::error_code &ec) noexcept
ec.clear();
int status;
- ::waitpid(p.pid, &status, 0); //just to clean it up
+ ::waitpid(p.pid, &status, WNOHANG); //just to clean it up
}
inline void terminate(const child_handle &p)
diff --git a/boost/process/detail/posix/wait_for_exit.hpp b/boost/process/detail/posix/wait_for_exit.hpp
index 5eadc9725c..376e480251 100644
--- a/boost/process/detail/posix/wait_for_exit.hpp
+++ b/boost/process/detail/posix/wait_for_exit.hpp
@@ -54,11 +54,35 @@ inline bool wait_until(
const std::chrono::time_point<Clock, Duration>& time_out,
std::error_code & ec) noexcept
{
-
::sigset_t sigset;
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGCHLD);
+ //I need to set the signal, because it might be ignore / default, in which case sigwait might not work.
+
+ using _signal_t = void(*)(int);
+ static thread_local _signal_t sigchld_handler = SIG_DFL;
+
+ struct signal_interceptor_t
+ {
+ static void handler_func(int val)
+ {
+ if ((sigchld_handler != SIG_DFL) && (sigchld_handler != SIG_IGN))
+ sigchld_handler(val);
+ }
+ signal_interceptor_t() { sigchld_handler = ::signal(SIGCHLD, &handler_func); }
+ ~signal_interceptor_t() { ::signal(SIGCHLD, sigchld_handler); sigchld_handler = SIG_DFL;}
+
+ } signal_interceptor{};
+
+ if (sigemptyset(&sigset) != 0)
+ {
+ ec = get_last_error();
+ return false;
+ }
+ if (sigaddset(&sigset, SIGCHLD) != 0)
+ {
+ ec = get_last_error();
+ return false;
+ }
auto get_timespec =
[](const Duration & dur)
@@ -69,8 +93,8 @@ inline bool wait_until(
return ts;
};
- pid_t ret;
- int status;
+ int ret;
+ int status{0};
struct ::sigaction old_sig;
if (-1 == ::sigaction(SIGCHLD, nullptr, &old_sig))
@@ -80,6 +104,7 @@ inline bool wait_until(
}
bool timed_out;
+
#if defined(BOOST_POSIX_HAS_SIGTIMEDWAIT)
do
{
@@ -113,9 +138,16 @@ inline bool wait_until(
{
auto ts = get_timespec(time_out - Clock::now());
::timespec rem;
- ::nanosleep(&ts, &rem);
- while (rem.tv_sec > 0 || rem.tv_nsec > 0)
- ::nanosleep(&rem, &rem);
+ while (ts.tv_sec > 0 || ts.tv_nsec > 0)
+ {
+ if (::nanosleep(&ts, &rem) != 0)
+ {
+ auto err = errno;
+ if ((err == EINVAL) || (err == EFAULT))
+ break;
+ }
+ ts = get_timespec(time_out - Clock::now());
+ }
::exit(0);
}
@@ -125,7 +157,7 @@ inline bool wait_until(
~child_cleaner_t()
{
int res;
- ::kill(pid, -15);
+ ::kill(pid, SIGKILL);
::waitpid(pid, &res, WNOHANG);
}
};
@@ -133,19 +165,21 @@ inline bool wait_until(
do
{
- int ret_sig = 0;
+ int sig_{0};
if ((::waitpid(timeout_pid, &status, WNOHANG) != 0)
- && (WIFEXITED(status) || WIFSIGNALED(status)))
- ret_sig = ::sigwait(&sigset, nullptr);
- errno = 0;
+ && (WIFEXITED(status) || WIFSIGNALED(status)))
- ret = ::waitpid(p.pid, &status, WNOHANG);
+ return false;
- if ((ret_sig == SIGCHLD) &&
+ ret = ::sigwait(&sigset, &sig_);
+ errno = 0;
+
+ if ((sig_ == SIGCHLD) &&
(old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
old_sig.sa_handler(ret);
- if (ret <= 0)
+ ret = ::waitpid(p.pid, &status, WNOHANG);
+ if (ret == 0) // == > is running
{
timed_out = Clock::now() >= time_out;
if (timed_out)
diff --git a/boost/process/detail/posix/wait_group.hpp b/boost/process/detail/posix/wait_group.hpp
index 9dc2498031..d12cce1064 100644
--- a/boost/process/detail/posix/wait_group.hpp
+++ b/boost/process/detail/posix/wait_group.hpp
@@ -59,15 +59,14 @@ inline bool wait_until(
std::error_code & ec) noexcept
{
- ::sigset_t sigset;
::siginfo_t siginfo;
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGCHLD);
-
+ bool timed_out = false;
+ int ret;
- auto get_timespec =
- [](const Duration & dur)
+#if defined(BOOST_POSIX_HAS_SIGTIMEDWAIT)
+ auto get_timespec =
+ +[](const Duration & dur)
{
::timespec ts;
ts.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(dur).count();
@@ -75,9 +74,18 @@ inline bool wait_until(
return ts;
};
+ ::sigset_t sigset;
- bool timed_out = false;
- int ret;
+ if (sigemptyset(&sigset) != 0)
+ {
+ ec = get_last_error();
+ return false;
+ }
+ if (sigaddset(&sigset, SIGCHLD) != 0)
+ {
+ ec = get_last_error();
+ return false;
+ }
struct ::sigaction old_sig;
if (-1 == ::sigaction(SIGCHLD, nullptr, &old_sig))
@@ -86,7 +94,6 @@ inline bool wait_until(
return false;
}
-#if defined(BOOST_POSIX_HAS_SIGTIMEDWAIT)
do
{
auto ts = get_timespec(time_out - Clock::now());
@@ -98,80 +105,58 @@ inline bool wait_until(
ret = ::waitpid(-p.grp, &siginfo.si_status, 0); //so in case it exited, we wanna reap it first
if (ret == -1)
{
- ec = get_last_error();
- return false;
+ if ((errno == ECHILD) || (errno == ESRCH))
+ {
+ ec.clear();
+ return true;
+ }
+ else
+ {
+ ec = get_last_error();
+ return false;
+ }
}
- //check if we're done
+ //check if we're done ->
ret = ::waitid(P_PGID, p.grp, &siginfo, WEXITED | WNOHANG);
+ }
+ while (((ret != -1) || ((errno != ECHILD) && (errno != ESRCH))) && !(timed_out = (Clock::now() > time_out)));
- }
- while (((ret != -1) || (errno != ECHILD)) && !(timed_out = (Clock::now() > time_out)));
-#else
- //if we do not have sigtimedwait, we fork off a child process to get the signal in time
- pid_t timeout_pid = ::fork();
- if (timeout_pid == -1)
+ if (errno != ECHILD)
{
ec = boost::process::detail::get_last_error();
- return true;
+ return !timed_out;
}
- else if (timeout_pid == 0)
+ else
{
- auto ts = get_timespec(time_out - Clock::now());
- ::setpgid(0, p.grp);
- ::nanosleep(&ts, nullptr);
- ::exit(0);
+ ec.clear();
+ return true; //even if timed out, there are no child proccessess left
}
- struct child_cleaner_t
- {
- pid_t pid;
- ~child_cleaner_t()
- {
- int res;
- ::kill(pid, -15);
- ::waitpid(pid, &res, WNOHANG);
- }
- };
- child_cleaner_t child_cleaner{timeout_pid};
+#else
+ ::timespec sleep_interval;
+ sleep_interval.tv_sec = 0;
+ sleep_interval.tv_nsec = 1000000;
- do
- {
- int ret_sig = 0;
- int status;
- if ((::waitpid(timeout_pid, &status, WNOHANG) != 0)
- && (WIFEXITED(status) || WIFSIGNALED(status)))
- ret = ::sigwait(&sigset, nullptr);
- errno = 0;
- if ((ret == SIGCHLD) && (old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
- old_sig.sa_handler(ret);
- ret = ::waitpid(-p.grp, &siginfo.si_status, 0); //so in case it exited, we wanna reap it first
+ while (!(timed_out = (Clock::now() > time_out)))
+ {
+ ret = ::waitid(P_PGID, p.grp, &siginfo, WEXITED | WSTOPPED | WNOHANG);
if (ret == -1)
{
- ec = get_last_error();
+ if ((errno == ECHILD) || (errno == ESRCH))
+ {
+ ec.clear();
+ return true;
+ }
+ ec = boost::process::detail::get_last_error();
return false;
}
-
- //check if we're done
- ret = ::waitid(P_PGID, p.grp, &siginfo, WEXITED | WNOHANG);
-
+ //we can wait, because unlike in the wait_for_exit, we have no race condition regarding eh exit code.
+ ::nanosleep(&sleep_interval, nullptr);
}
- while (((ret != -1) || (errno != ECHILD)) && !(timed_out = (Clock::now() > time_out)));
-
+ return !timed_out;
#endif
-
- if (errno != ECHILD)
- {
- ec = boost::process::detail::get_last_error();
- return !timed_out;
- }
- else
- {
- ec.clear();
- return true; //even if timed out, there are no child proccessess left
- }
-
}
template< class Clock, class Duration >
diff --git a/boost/process/detail/used_handles.hpp b/boost/process/detail/used_handles.hpp
new file mode 100644
index 0000000000..4d56af3571
--- /dev/null
+++ b/boost/process/detail/used_handles.hpp
@@ -0,0 +1,81 @@
+// 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_USED_HANDLES_HPP_
+#define BOOST_PROCESS_DETAIL_USED_HANDLES_HPP_
+
+#include <type_traits>
+#include <boost/fusion/include/filter_if.hpp>
+#include <boost/fusion/include/for_each.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/handles.hpp>
+#include <boost/process/detail/posix/asio_fwd.hpp>
+#else
+#include <boost/process/detail/windows/handles.hpp>
+#include <boost/process/detail/windows/asio_fwd.hpp>
+#endif
+
+namespace boost { namespace process { namespace detail {
+
+struct uses_handles
+{
+ //If you get an error here, you must add a `get_handles` function that returns a range or a single handle value
+ void get_used_handles() const;
+};
+
+template<typename T>
+struct does_use_handle: std::is_base_of<uses_handles, T> {};
+
+template<typename T>
+struct does_use_handle<T&> : std::is_base_of<uses_handles, T> {};
+
+template<typename T>
+struct does_use_handle<const T&> : std::is_base_of<uses_handles, T> {};
+
+template<typename Char, typename Sequence>
+class executor;
+
+template<typename Func>
+struct foreach_handle_invocator
+{
+ Func & func;
+ foreach_handle_invocator(Func & func) : func(func) {}
+
+
+ template<typename Range>
+ void invoke(const Range & range) const
+ {
+ for (auto handle_ : range)
+ func(handle_);
+
+ }
+ void invoke(::boost::process::detail::api::native_handle_type handle) const {func(handle);};
+
+ template<typename T>
+ void operator()(T & val) const {invoke(val.get_used_handles());}
+};
+
+template<typename Executor, typename Function>
+void foreach_used_handle(Executor &exec, Function &&func)
+{
+ boost::fusion::for_each(boost::fusion::filter_if<does_use_handle<boost::mpl::_>>(exec.seq),
+ foreach_handle_invocator<Function>(func));
+}
+
+template<typename Executor>
+std::vector<::boost::process::detail::api::native_handle_type>
+ get_used_handles(Executor &exec)
+{
+ std::vector<::boost::process::detail::api::native_handle_type> res;
+ foreach_used_handle(exec, [&](::boost::process::detail::api::native_handle_type handle){res.push_back(handle);});
+ return res;
+}
+
+
+
+}}}
+
+#endif /* BOOST_PROCESS_DETAIL_USED_HANDLES_HPP_ */
diff --git a/boost/process/detail/windows/async_in.hpp b/boost/process/detail/windows/async_in.hpp
index 2a758337b8..cd45835af4 100644
--- a/boost/process/detail/windows/async_in.hpp
+++ b/boost/process/detail/windows/async_in.hpp
@@ -17,19 +17,20 @@
#include <boost/asio/write.hpp>
#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/used_handles.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_context
+ ::boost::process::detail::windows::require_io_context,
+ ::boost::process::detail::uses_handles
{
Buffer & buf;
@@ -42,6 +43,11 @@ struct async_in_buffer : ::boost::process::detail::windows::handler_base_ext,
std::shared_ptr<boost::process::async_pipe> pipe;
+ ::boost::winapi::HANDLE_ get_used_handles() const
+ {
+ return std::move(*pipe).source().native_handle();
+ }
+
async_in_buffer(Buffer & buf) : buf(buf)
{
}
diff --git a/boost/process/detail/windows/async_out.hpp b/boost/process/detail/windows/async_out.hpp
index 525cbafef0..ed39b03403 100644
--- a/boost/process/detail/windows/async_out.hpp
+++ b/boost/process/detail/windows/async_out.hpp
@@ -16,6 +16,7 @@
#include <boost/winapi/error_codes.hpp>
#include <boost/asio/read.hpp>
#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/windows/asio_fwd.hpp>
#include <istream>
@@ -108,12 +109,18 @@ struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,
template<int p1, int p2, typename Type>
struct async_out_future : ::boost::process::detail::windows::handler_base_ext,
- ::boost::process::detail::windows::require_io_context
+ ::boost::process::detail::windows::require_io_context,
+ ::boost::process::detail::uses_handles
{
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>();
+ ::boost::winapi::HANDLE_ get_used_handles() const
+ {
+ return std::move(*pipe).sink().native_handle();
+ }
+
async_out_future(std::future<Type> & fut)
{
diff --git a/boost/process/detail/windows/async_pipe.hpp b/boost/process/detail/windows/async_pipe.hpp
index f06653962a..06d5f2d854 100644
--- a/boost/process/detail/windows/async_pipe.hpp
+++ b/boost/process/detail/windows/async_pipe.hpp
@@ -40,23 +40,30 @@ class async_pipe
{
::boost::asio::windows::stream_handle _source;
::boost::asio::windows::stream_handle _sink ;
+
+ inline async_pipe(boost::asio::io_context & ios_source,
+ boost::asio::io_context & ios_sink,
+ const std::string & name, bool private_);
+
public:
typedef ::boost::winapi::HANDLE_ native_handle_type;
typedef ::boost::asio::windows::stream_handle handle_type;
- inline async_pipe(boost::asio::io_context & ios,
- const std::string & name = make_pipe_name())
- : async_pipe(ios, ios, name) {}
+ async_pipe(boost::asio::io_context & ios) : async_pipe(ios, ios, make_pipe_name(), true) {}
+ async_pipe(boost::asio::io_context & ios_source, boost::asio::io_context & ios_sink)
+ : async_pipe(ios_source, ios_sink, make_pipe_name(), true) {}
+
+ async_pipe(boost::asio::io_context & ios, const std::string & name)
+ : async_pipe(ios, ios, name, false) {}
+
+ async_pipe(boost::asio::io_context & ios_source, boost::asio::io_context & ios_sink, const std::string & name)
+ : async_pipe(ios_source, ios_sink, name, false) {}
+
- inline async_pipe(boost::asio::io_context & ios_source,
- boost::asio::io_context & 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::winapi::INVALID_HANDLE_VALUE_);
- rhs._sink .assign (::boost::winapi::INVALID_HANDLE_VALUE_);
}
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(::boost::asio::io_context & ios_source,
@@ -191,13 +198,15 @@ public:
handle_type source(::boost::asio::io_context& ios) &&
{
::boost::asio::windows::stream_handle stolen(ios.get_executor(), _source.native_handle());
- _source.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
+ boost::system::error_code ec;
+ _source.assign(::boost::winapi::INVALID_HANDLE_VALUE_, ec);
return stolen;
}
handle_type sink (::boost::asio::io_context& ios) &&
{
::boost::asio::windows::stream_handle stolen(ios.get_executor(), _sink.native_handle());
- _sink.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
+ boost::system::error_code ec;
+ _sink.assign(::boost::winapi::INVALID_HANDLE_VALUE_, ec);
return stolen;
}
@@ -235,12 +244,11 @@ public:
}
};
-
-
async_pipe::async_pipe(const async_pipe& p) :
_source(const_cast<handle_type&>(p._source).get_executor()),
_sink (const_cast<handle_type&>(p._sink).get_executor())
{
+
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::winapi::HANDLE_ source;
@@ -266,14 +274,16 @@ async_pipe::async_pipe(const async_pipe& p) :
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
- _source.assign(source);
- _sink. assign(sink);
+ if (source != ::boost::winapi::INVALID_HANDLE_VALUE_)
+ _source.assign(source);
+ if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
+ _sink. assign(sink);
}
async_pipe::async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
- const std::string & name) : _source(ios_source), _sink(ios_sink)
+ const std::string & name, bool private_) : _source(ios_source), _sink(ios_sink)
{
static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary
@@ -285,7 +295,7 @@ async_pipe::async_pipe(boost::asio::io_context & ios_source,
#endif
::boost::winapi::PIPE_ACCESS_INBOUND_
| FILE_FLAG_OVERLAPPED_, //write flag
- 0, 1, 8192, 8192, 0, nullptr);
+ 0, private_ ? 1 : ::boost::winapi::PIPE_UNLIMITED_INSTANCES_, 8192, 8192, 0, nullptr);
if (source == boost::winapi::INVALID_HANDLE_VALUE_)
@@ -310,6 +320,44 @@ async_pipe::async_pipe(boost::asio::io_context & ios_source,
_sink.assign(sink);
}
+template<class CharT, class Traits>
+async_pipe& async_pipe::operator=(const basic_pipe<CharT, Traits> & p)
+{
+ auto proc = ::boost::winapi::GetCurrentProcess();
+
+ ::boost::winapi::HANDLE_ source;
+ ::boost::winapi::HANDLE_ sink;
+
+ //cannot get the handle from a const object.
+ auto source_in = p.native_source();
+ auto sink_in = p.native_sink();
+
+ if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
+ source = ::boost::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::winapi::DuplicateHandle(
+ proc, source_in.native_handle(), proc, &source, 0,
+ static_cast<::boost::winapi::BOOL_>(true),
+ ::boost::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
+ sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::winapi::DuplicateHandle(
+ proc, sink_in.native_handle(), proc, &sink, 0,
+ static_cast<::boost::winapi::BOOL_>(true),
+ ::boost::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ //so we also assign the io_context
+ if (source != ::boost::winapi::INVALID_HANDLE_VALUE_)
+ _source.assign(source);
+
+ if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
+ _sink.assign(sink);
+
+ return *this;
+}
+
async_pipe& async_pipe::operator=(const async_pipe & p)
{
auto proc = ::boost::winapi::GetCurrentProcess();
@@ -321,6 +369,8 @@ async_pipe& async_pipe::operator=(const async_pipe & p)
auto &source_in = const_cast<::boost::asio::windows::stream_handle &>(p._source);
auto &sink_in = const_cast<::boost::asio::windows::stream_handle &>(p._sink);
+ source_in.get_executor();
+
if (source_in.native_handle() == ::boost::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
@@ -338,24 +388,23 @@ async_pipe& async_pipe::operator=(const async_pipe & p)
throw_last_error("Duplicate Pipe Failed");
//so we also assign the io_context
- _source = ::boost::asio::windows::stream_handle(source_in.get_executor(), source);
- _sink = ::boost::asio::windows::stream_handle(source_in.get_executor(), sink);
+ if (source != ::boost::winapi::INVALID_HANDLE_VALUE_)
+ _source = ::boost::asio::windows::stream_handle(source_in.get_executor(), source);
+ else
+ _source = ::boost::asio::windows::stream_handle(source_in.get_executor());
+
+ if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
+ _sink = ::boost::asio::windows::stream_handle(source_in.get_executor(), sink);
+ else
+ _sink = ::boost::asio::windows::stream_handle(source_in.get_executor());
return *this;
}
async_pipe& async_pipe::operator=(async_pipe && rhs)
{
- if (_source.native_handle() != ::boost::winapi::INVALID_HANDLE_VALUE_)
- ::boost::winapi::CloseHandle(_source.native_handle());
-
- if (_sink.native_handle() != ::boost::winapi::INVALID_HANDLE_VALUE_)
- ::boost::winapi::CloseHandle(_sink.native_handle());
-
- _source.assign(rhs._source.native_handle());
- _sink .assign(rhs._sink .native_handle());
- rhs._source.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
- rhs._sink .assign(::boost::winapi::INVALID_HANDLE_VALUE_);
+ _source = std::move(rhs._source);
+ _sink = std::move(rhs._sink);
return *this;
}
diff --git a/boost/process/detail/windows/basic_pipe.hpp b/boost/process/detail/windows/basic_pipe.hpp
index 28f5651d75..3cf9044747 100644
--- a/boost/process/detail/windows/basic_pipe.hpp
+++ b/boost/process/detail/windows/basic_pipe.hpp
@@ -98,7 +98,7 @@ public:
return static_cast<int_type>(read_len);
}
- bool is_open()
+ bool is_open() const
{
return (_source != ::boost::winapi::INVALID_HANDLE_VALUE_) ||
(_sink != ::boost::winapi::INVALID_HANDLE_VALUE_);
@@ -152,7 +152,7 @@ basic_pipe<Char, Traits>::basic_pipe(const std::string & name)
name_.c_str(),
::boost::winapi::PIPE_ACCESS_INBOUND_
| FILE_FLAG_OVERLAPPED_, //write flag
- 0, 1, 8192, 8192, 0, nullptr);
+ 0, ::boost::winapi::PIPE_UNLIMITED_INSTANCES_, 8192, 8192, 0, nullptr);
if (source == boost::winapi::INVALID_HANDLE_VALUE_)
::boost::process::detail::throw_last_error("create_named_pipe() failed");
diff --git a/boost/process/detail/windows/file_in.hpp b/boost/process/detail/windows/file_in.hpp
index c39235fb3d..c56f91ef08 100644
--- a/boost/process/detail/windows/file_in.hpp
+++ b/boost/process/detail/windows/file_in.hpp
@@ -13,16 +13,20 @@
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/used_handles.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
+struct file_in : public ::boost::process::detail::handler_base,
+ ::boost::process::detail::uses_handles
{
file_descriptor file;
::boost::winapi::HANDLE_ handle = file.handle();
+ ::boost::winapi::HANDLE_ get_used_handles() const { return handle; }
+
template<typename T>
file_in(T&& t) : file(std::forward<T>(t), file_descriptor::read) {}
file_in(FILE * f) : handle(reinterpret_cast<::boost::winapi::HANDLE_>(_get_osfhandle(_fileno(f)))) {}
diff --git a/boost/process/detail/windows/file_out.hpp b/boost/process/detail/windows/file_out.hpp
index db14b3907d..88f0848d81 100644
--- a/boost/process/detail/windows/file_out.hpp
+++ b/boost/process/detail/windows/file_out.hpp
@@ -14,16 +14,21 @@
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/used_handles.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
+struct file_out : public ::boost::process::detail::handler_base,
+ ::boost::process::detail::uses_handles
{
file_descriptor file;
::boost::winapi::HANDLE_ handle = file.handle();
+ ::boost::winapi::HANDLE_ get_used_handles() const { return 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)))) {}
diff --git a/boost/process/detail/windows/group_ref.hpp b/boost/process/detail/windows/group_ref.hpp
index bbbe4317ba..6e8fe71f2a 100644
--- a/boost/process/detail/windows/group_ref.hpp
+++ b/boost/process/detail/windows/group_ref.hpp
@@ -6,9 +6,10 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_GROUP_REF_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_GROUP_REF_HPP_
+#include <boost/winapi/process.hpp>
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/windows/group_handle.hpp>
-#include <boost/winapi/process.hpp>
+#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/windows/handler.hpp>
namespace boost { namespace process {
@@ -17,10 +18,12 @@ namespace detail { namespace windows {
-struct group_ref : handler_base_ext
+struct group_ref : handler_base_ext, ::boost::process::detail::uses_handles
{
::boost::winapi::HANDLE_ handle;
+ ::boost::winapi::HANDLE_ get_used_handles() const { return handle; }
+
explicit group_ref(group_handle &g) :
handle(g.handle())
{}
diff --git a/boost/process/detail/windows/handle_workaround.hpp b/boost/process/detail/windows/handle_workaround.hpp
new file mode 100644
index 0000000000..a6414ae3f6
--- /dev/null
+++ b/boost/process/detail/windows/handle_workaround.hpp
@@ -0,0 +1,262 @@
+// Copyright (c) 2018 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_HANDLE_WORKAROUND_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_HANDLE_WORKAROUND_HPP_
+
+#include <boost/winapi/basic_types.hpp>
+#include <boost/winapi/dll.hpp>
+#include <boost/winapi/access_rights.hpp>
+//#define BOOST_USE_WINDOWS_H 1
+
+#if defined( BOOST_USE_WINDOWS_H )
+#include <Winternl.h>
+#endif
+
+
+namespace boost { namespace process { namespace detail { namespace windows { namespace workaround
+{
+
+
+typedef struct _SYSTEM_HANDLE_ENTRY_
+{
+ ::boost::winapi::ULONG_ OwnerPid;
+ ::boost::winapi::BYTE_ ObjectType;
+ ::boost::winapi::BYTE_ HandleFlags;
+ ::boost::winapi::USHORT_ HandleValue;
+ ::boost::winapi::PVOID_ ObjectPointer;
+ ::boost::winapi::ULONG_ AccessMask;
+} SYSTEM_HANDLE_ENTRY_, *PSYSTEM_HANDLE_ENTRY_;
+
+typedef struct _SYSTEM_HANDLE_INFORMATION_
+{
+ ::boost::winapi::ULONG_ Count;
+ SYSTEM_HANDLE_ENTRY_ Handle[1];
+} SYSTEM_HANDLE_INFORMATION_, *PSYSTEM_HANDLE_INFORMATION_;
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+using UNICODE_STRING_ = ::UNICODE_STRING;
+using GENERIC_MAPPING_ = ::GENERIC_MAPPING;
+using OBJECT_INFORMATION_CLASS_ = ::OBJECT_INFORMATION_CLASS;
+
+constexpr static OBJECT_INFORMATION_CLASS_ ObjectTypeInformation = ::OBJECT_INFORMATION_CLASS::ObjectTypeInformation;
+
+typedef struct _OBJECT_TYPE_INFORMATION_ {
+ UNICODE_STRING TypeName;
+ ULONG TotalNumberOfObjects;
+ ULONG TotalNumberOfHandles;
+ ULONG TotalPagedPoolUsage;
+ ULONG TotalNonPagedPoolUsage;
+ ULONG TotalNamePoolUsage;
+ ULONG TotalHandleTableUsage;
+ ULONG HighWaterNumberOfObjects;
+ ULONG HighWaterNumberOfHandles;
+ ULONG HighWaterPagedPoolUsage;
+ ULONG HighWaterNonPagedPoolUsage;
+ ULONG HighWaterNamePoolUsage;
+ ULONG HighWaterHandleTableUsage;
+ ULONG InvalidAttributes;
+ GENERIC_MAPPING GenericMapping;
+ ULONG ValidAccessMask;
+ BOOLEAN SecurityRequired;
+ BOOLEAN MaintainHandleCount;
+ UCHAR TypeIndex;
+ CHAR ReservedByte;
+ ULONG PoolType;
+ ULONG DefaultPagedPoolCharge;
+ ULONG DefaultNonPagedPoolCharge;
+} OBJECT_TYPE_INFORMATION_, *POBJECT_TYPE_INFORMATION_;
+
+#else
+
+typedef enum _OBJECT_INFORMATION_CLASS_
+{
+ ObjectBasicInformation,
+ ObjectNameInformation,
+ ObjectTypeInformation,
+ ObjectAllInformation,
+ ObjectDataInformation
+} OBJECT_INFORMATION_CLASS_, *POBJECT_INFORMATION_CLASS_;
+
+typedef struct _UNICODE_STRING_ {
+ ::boost::winapi::USHORT_ Length;
+ ::boost::winapi::USHORT_ MaximumLength;
+ ::boost::winapi::LPWSTR_ Buffer;
+} UNICODE_STRING_, *PUNICODE_STRING_;
+
+typedef struct _GENERIC_MAPPING_ {
+ ::boost::winapi::ACCESS_MASK_ GenericRead;
+ ::boost::winapi::ACCESS_MASK_ GenericWrite;
+ ::boost::winapi::ACCESS_MASK_ GenericExecute;
+ ::boost::winapi::ACCESS_MASK_ GenericAll;
+} GENERIC_MAPPING_;
+
+#endif
+
+typedef struct _OBJECT_BASIC_INFORMATION {
+ ::boost::winapi::ULONG_ Attributes;
+ ::boost::winapi::ACCESS_MASK_ GrantedAccess;
+ ::boost::winapi::ULONG_ HandleCount;
+ ::boost::winapi::ULONG_ PointerCount;
+ ::boost::winapi::ULONG_ PagedPoolUsage;
+ ::boost::winapi::ULONG_ NonPagedPoolUsage;
+ ::boost::winapi::ULONG_ Reserved[3];
+ ::boost::winapi::ULONG_ NameInformationLength;
+ ::boost::winapi::ULONG_ TypeInformationLength;
+ ::boost::winapi::ULONG_ SecurityDescriptorLength;
+ ::boost::winapi::LARGE_INTEGER_ CreateTime;
+} OBJECT_BASIC_INFORMATION_, *POBJECT_BASIC_INFORMATION_;
+
+typedef struct _OBJECT_NAME_INFORMATION {
+ UNICODE_STRING_ Name;
+} OBJECT_NAME_INFORMATION_, *POBJECT_NAME_INFORMATION_;
+
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+extern "C"
+{
+
+using SYSTEM_INFORMATION_CLASS_ = ::SYSTEM_INFORMATION_CLASS;
+constexpr static SYSTEM_INFORMATION_CLASS_ SystemHandleInformation_ = static_cast<SYSTEM_INFORMATION_CLASS_>(16);
+
+inline ::boost::winapi::NTSTATUS_ nt_system_query_information(
+ SYSTEM_INFORMATION_CLASS SystemInformationClass,
+ void * SystemInformation,
+ ::boost::winapi::ULONG_ SystemInformationLength,
+ ::boost::winapi::PULONG_ ReturnLength)
+{
+ return ::NtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
+}
+
+inline ::boost::winapi::NTSTATUS_ nt_query_object(
+ ::boost::winapi::HANDLE_ Handle,
+ OBJECT_INFORMATION_CLASS_ ObjectInformationClass,
+ ::boost::winapi::PVOID_ ObjectInformation,
+ ::boost::winapi::ULONG_ ObjectInformationLength,
+ ::boost::winapi::PULONG_ ReturnLength
+)
+{
+ return ::NtQueryObject(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength);
+}
+
+}
+
+#else
+
+//this import workaround is to keep it a header-only library. and enums cannot be imported from the winapi.
+
+extern "C"
+{
+
+typedef enum _SYSTEM_INFORMATION_CLASS_
+{
+ SystemBasicInformation_ = 0,
+ SystemProcessorInformation_ = 1,
+ SystemPerformanceInformation_ = 2,
+ SystemTimeOfDayInformation_ = 3,
+ SystemProcessInformation_ = 5,
+ SystemProcessorPerformanceInformation_ = 8,
+ SystemHandleInformation_ = 16,
+ SystemPagefileInformation_ = 18,
+ SystemInterruptInformation_ = 23,
+ SystemExceptionInformation_ = 33,
+ SystemRegistryQuotaInformation_ = 37,
+ SystemLookasideInformation_ = 45
+} SYSTEM_INFORMATION_CLASS_;
+
+
+typedef struct _OBJECT_TYPE_INFORMATION_ {
+ UNICODE_STRING_ TypeName;
+ ::boost::winapi::ULONG_ TotalNumberOfObjects;
+ ::boost::winapi::ULONG_ TotalNumberOfHandles;
+ ::boost::winapi::ULONG_ TotalPagedPoolUsage;
+ ::boost::winapi::ULONG_ TotalNonPagedPoolUsage;
+ ::boost::winapi::ULONG_ TotalNamePoolUsage;
+ ::boost::winapi::ULONG_ TotalHandleTableUsage;
+ ::boost::winapi::ULONG_ HighWaterNumberOfObjects;
+ ::boost::winapi::ULONG_ HighWaterNumberOfHandles;
+ ::boost::winapi::ULONG_ HighWaterPagedPoolUsage;
+ ::boost::winapi::ULONG_ HighWaterNonPagedPoolUsage;
+ ::boost::winapi::ULONG_ HighWaterNamePoolUsage;
+ ::boost::winapi::ULONG_ HighWaterHandleTableUsage;
+ ::boost::winapi::ULONG_ InvalidAttributes;
+ GENERIC_MAPPING_ GenericMapping;
+ ::boost::winapi::ULONG_ ValidAccessMask;
+ ::boost::winapi::BOOLEAN_ SecurityRequired;
+ ::boost::winapi::BOOLEAN_ MaintainHandleCount;
+ ::boost::winapi::UCHAR_ TypeIndex;
+ ::boost::winapi::CHAR_ ReservedByte;
+ ::boost::winapi::ULONG_ PoolType;
+ ::boost::winapi::ULONG_ DefaultPagedPoolCharge;
+ ::boost::winapi::ULONG_ DefaultNonPagedPoolCharge;
+} OBJECT_TYPE_INFORMATION_, *POBJECT_TYPE_INFORMATION_;
+
+
+
+/*
+__kernel_entry NTSTATUS NtQuerySystemInformation(
+ IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
+ OUT PVOID SystemInformation,
+ IN ULONG SystemInformationLength,
+ OUT PULONG ReturnLength
+);
+ */
+typedef ::boost::winapi::NTSTATUS_ (__kernel_entry *nt_system_query_information_p )(
+ SYSTEM_INFORMATION_CLASS_,
+ void *,
+ ::boost::winapi::ULONG_,
+ ::boost::winapi::PULONG_);
+/*
+__kernel_entry NTSYSCALLAPI NTSTATUS NtQueryObject(
+ HANDLE Handle,
+ OBJECT_INFORMATION_CLASS ObjectInformationClass,
+ PVOID ObjectInformation,
+ ULONG ObjectInformationLength,
+ PULONG ReturnLength
+);
+ */
+
+typedef ::boost::winapi::NTSTATUS_ (__kernel_entry *nt_query_object_p )(
+ ::boost::winapi::HANDLE_,
+ OBJECT_INFORMATION_CLASS_,
+ void *,
+ ::boost::winapi::ULONG_,
+ ::boost::winapi::PULONG_);
+
+}
+
+inline ::boost::winapi::NTSTATUS_ nt_system_query_information(
+ SYSTEM_INFORMATION_CLASS_ SystemInformationClass,
+ void *SystemInformation,
+ ::boost::winapi::ULONG_ SystemInformationLength,
+ ::boost::winapi::PULONG_ ReturnLength)
+{
+ static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(L"Ntdll.dll");
+ static nt_system_query_information_p f = reinterpret_cast<nt_system_query_information_p>(::boost::winapi::get_proc_address(h, "NtQuerySystemInformation"));
+
+ return (*f)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
+}
+
+
+inline ::boost::winapi::BOOL_ nt_query_object(
+ ::boost::winapi::HANDLE_ Handle,
+ OBJECT_INFORMATION_CLASS_ ObjectInformationClass,
+ void *ObjectInformation,
+ ::boost::winapi::ULONG_ ObjectInformationLength,
+ ::boost::winapi::PULONG_ ReturnLength)
+{
+ static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(L"Ntdll.dll");
+ static nt_query_object_p f = reinterpret_cast<nt_query_object_p>(::boost::winapi::get_proc_address(h, "NtQueryObject"));
+
+ return (*f)(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength);
+}
+
+#endif
+
+}}}}}
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_ */
diff --git a/boost/process/detail/windows/handles.hpp b/boost/process/detail/windows/handles.hpp
new file mode 100644
index 0000000000..5ba5780e9f
--- /dev/null
+++ b/boost/process/detail/windows/handles.hpp
@@ -0,0 +1,176 @@
+// Copyright (c) 2019 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_HANDLES_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_HANDLES_HPP_
+
+#include <vector>
+#include <system_error>
+#include <boost/process/detail/windows/handle_workaround.hpp>
+#include <boost/process/detail/windows/handler.hpp>
+#include <boost/winapi/get_current_process_id.hpp>
+
+namespace boost { namespace process { namespace detail {
+
+
+template<typename Executor, typename Function>
+void foreach_used_handle(Executor &exec, Function &&func);
+
+
+namespace windows {
+
+
+using native_handle_type = ::boost::winapi::HANDLE_ ;
+
+inline std::vector<native_handle_type> get_handles(std::error_code & ec)
+{
+ auto pid = ::boost::winapi::GetCurrentProcessId();
+
+ std::vector<char> buffer(2048);
+ constexpr static auto STATUS_INFO_LENGTH_MISMATCH_ = static_cast<::boost::winapi::NTSTATUS_>(0xC0000004l);
+ auto info_pointer = reinterpret_cast<workaround::SYSTEM_HANDLE_INFORMATION_*>(buffer.data());
+
+ ::boost::winapi::NTSTATUS_ nt_status = STATUS_INFO_LENGTH_MISMATCH_;
+
+ for (int cnt = 0;
+ nt_status == STATUS_INFO_LENGTH_MISMATCH_;
+ nt_status = workaround::nt_system_query_information(
+ workaround::SystemHandleInformation_,
+ info_pointer, buffer.size(),
+ NULL))
+ {
+ buffer.resize(buffer.size() * 2);
+ info_pointer = reinterpret_cast<workaround::SYSTEM_HANDLE_INFORMATION_*>(buffer.data());
+ }
+
+
+ if (nt_status < 0 || nt_status > 0x7FFFFFFF)
+ {
+ ec = ::boost::process::detail::get_last_error();
+ return {};
+ }
+ else
+ ec.clear();
+
+ std::vector<native_handle_type> res;
+ for (auto itr = info_pointer->Handle; itr != (info_pointer->Handle + info_pointer->Count); itr++)
+ {
+ if (itr->OwnerPid == pid)
+ res.push_back(reinterpret_cast<native_handle_type>(static_cast<std::uintptr_t>(itr->HandleValue)));
+ }
+
+ return res;
+}
+
+inline std::vector<native_handle_type> get_handles()
+{
+ std::error_code ec;
+
+ auto res = get_handles(ec);
+ if (ec)
+ boost::process::detail::throw_error(ec, "NtQuerySystemInformation failed");
+
+ return res;
+}
+
+
+inline bool is_stream_handle(native_handle_type handle, std::error_code & ec)
+{
+ ::boost::winapi::ULONG_ actual_size;
+ auto nt_status = workaround::nt_query_object(
+ handle,
+ workaround::ObjectTypeInformation,
+ NULL,
+ 0, &actual_size);
+
+ std::vector<char> vec;
+ vec.resize(actual_size);
+
+ workaround::OBJECT_TYPE_INFORMATION_ * type_info_p = reinterpret_cast<workaround::OBJECT_TYPE_INFORMATION_*>(vec.data());
+ nt_status = workaround::nt_query_object(
+ handle,
+ workaround::ObjectTypeInformation,
+ type_info_p,
+ actual_size, &actual_size);
+
+ if (nt_status < 0 || nt_status > 0x7FFFFFFF)
+ {
+ ec = ::boost::process::detail::get_last_error();
+ return false;
+ }
+ else
+ ec.clear();
+
+ auto &nm = type_info_p->TypeName.Buffer;
+ return type_info_p->TypeName.Length >= 5 &&
+ nm[0] == L'F' &&
+ nm[1] == L'i' &&
+ nm[2] == L'l' &&
+ nm[3] == L'e' &&
+ nm[4] == L'\0';
+}
+
+
+inline bool is_stream_handle(native_handle_type handle)
+{
+ std::error_code ec;
+ auto res = is_stream_handle(handle, ec);
+ if (ec)
+ boost::process::detail::throw_error(ec, "NtQueryObject failed");
+
+ return res;
+}
+
+
+struct limit_handles_ : handler_base_ext
+{
+ mutable std::vector<::boost::winapi::HANDLE_> handles_with_inherit_flag;
+
+ template<typename Executor>
+ void on_setup(Executor & exec) const
+ {
+ auto all_handles = get_handles();
+ foreach_used_handle(exec,
+ [&](::boost::winapi::HANDLE_ handle)
+ {
+ auto itr = std::find(all_handles.begin(), all_handles .end(), handle);
+ DWORD flags = 0u;
+ if (itr != all_handles.end())
+ *itr = ::boost::winapi::INVALID_HANDLE_VALUE_;
+ else if ((::boost::winapi::GetHandleInformation(*itr, &flags) != 0)
+ &&((flags & ::boost::winapi::HANDLE_FLAG_INHERIT_) == 0)) //it is NOT inherited anyhow, so ignore too
+ *itr = ::boost::winapi::INVALID_HANDLE_VALUE_;
+ });
+
+ auto part_itr = std::partition(all_handles.begin(), all_handles.end(),
+ [](::boost::winapi::HANDLE_ handle) {return handle != ::boost::winapi::INVALID_HANDLE_VALUE_;});
+
+ all_handles.erase(part_itr, all_handles.end()); //remove invalid handles
+ handles_with_inherit_flag = std::move(all_handles);
+
+ for (auto handle : handles_with_inherit_flag)
+ ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, 0);
+ }
+
+ template<typename Executor>
+ void on_error(Executor & exec, const std::error_code & ec) const
+ {
+ for (auto handle : handles_with_inherit_flag)
+ ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_);
+ }
+
+ template<typename Executor>
+ void on_sucess(Executor & exec) const
+ {
+ for (auto handle : handles_with_inherit_flag)
+ ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_);
+ }
+
+};
+
+
+}}}}
+
+#endif //PROCESS_HANDLES_HPP
diff --git a/boost/process/detail/windows/null_in.hpp b/boost/process/detail/windows/null_in.hpp
index 5fd9ffb9e2..d29eb8f415 100644
--- a/boost/process/detail/windows/null_in.hpp
+++ b/boost/process/detail/windows/null_in.hpp
@@ -14,14 +14,18 @@
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/used_handles.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
+struct null_in : public ::boost::process::detail::handler_base, ::boost::process::detail::uses_handles
{
file_descriptor source{"NUL", file_descriptor::read};
+ ::boost::winapi::HANDLE_ get_used_handles() const { return source.handle(); }
+
+
public:
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
diff --git a/boost/process/detail/windows/null_out.hpp b/boost/process/detail/windows/null_out.hpp
index 0323deab78..0f80cf6cba 100644
--- a/boost/process/detail/windows/null_out.hpp
+++ b/boost/process/detail/windows/null_out.hpp
@@ -14,15 +14,18 @@
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/used_handles.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
+struct null_out : public ::boost::process::detail::handler_base, ::boost::process::detail::uses_handles
{
file_descriptor sink {"NUL", file_descriptor::write}; //works because it gets destroyed AFTER launch.
+ ::boost::winapi::HANDLE_ get_used_handles() const { return sink.handle(); }
+
template <typename WindowsExecutor>
void on_setup(WindowsExecutor &e) const;
};
diff --git a/boost/process/detail/windows/pipe_in.hpp b/boost/process/detail/windows/pipe_in.hpp
index 3cc1a10b90..39546eae62 100644
--- a/boost/process/detail/windows/pipe_in.hpp
+++ b/boost/process/detail/windows/pipe_in.hpp
@@ -12,14 +12,17 @@
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
+#include <boost/process/detail/used_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
+struct pipe_in : public ::boost::process::detail::handler_base, ::boost::process::detail::uses_handles
{
::boost::winapi::HANDLE_ handle;
+ ::boost::winapi::HANDLE_ get_used_handles() const { return handle; }
+
pipe_in(::boost::winapi::HANDLE_ handle) : handle(handle) {}
template<typename T> //async_pipe
diff --git a/boost/process/detail/windows/pipe_out.hpp b/boost/process/detail/windows/pipe_out.hpp
index 4cefa2fc28..125a34862d 100644
--- a/boost/process/detail/windows/pipe_out.hpp
+++ b/boost/process/detail/windows/pipe_out.hpp
@@ -13,6 +13,7 @@
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
+#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -20,10 +21,12 @@ namespace boost { namespace process { namespace detail { namespace windows {
template<int p1, int p2>
-struct pipe_out : public ::boost::process::detail::handler_base
+struct pipe_out : public ::boost::process::detail::handler_base, ::boost::process::detail::uses_handles
{
::boost::winapi::HANDLE_ handle;
+ ::boost::winapi::HANDLE_ get_used_handles() const { return handle; }
+
pipe_out(::boost::winapi::HANDLE_ handle) : handle(handle) {}
template<typename T>
pipe_out(T & p) : handle(p.native_sink())
diff --git a/boost/process/detail/windows/wait_group.hpp b/boost/process/detail/windows/wait_group.hpp
index 33e353f998..d00fd0c561 100644
--- a/boost/process/detail/windows/wait_group.hpp
+++ b/boost/process/detail/windows/wait_group.hpp
@@ -27,7 +27,7 @@ inline bool wait_impl(const group_handle & p, std::error_code & ec, std::chrono:
while (workaround::get_queued_completion_status(
p._io_port, &completion_code,
- &completion_key, &overlapped, wait_time))
+ &completion_key, &overlapped, static_cast<::boost::winapi::DWORD_>(wait_time)))
{
if (reinterpret_cast<::boost::winapi::HANDLE_>(completion_key) == p._job_object &&
completion_code == workaround::JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO_)
@@ -48,11 +48,11 @@ inline bool wait_impl(const group_handle & p, std::error_code & ec, std::chrono:
return false; //correct, nothing left.
}
//reduce the remaining wait time -> in case interrupted by something else
- if (wait_time != ::boost::winapi::infinite)
+ if (wait_time != static_cast<int>(::boost::winapi::infinite))
{
auto now = std::chrono::system_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
- wait_time -= diff.count();
+ wait_time -= static_cast<std::chrono::system_clock::rep>(diff.count());
start_time = now;
if (wait_time <= 0)
return true; //timeout with other source
diff --git a/boost/process/extend.hpp b/boost/process/extend.hpp
index 5d4eb2d515..3b022c69fe 100644
--- a/boost/process/extend.hpp
+++ b/boost/process/extend.hpp
@@ -7,6 +7,7 @@
#define BOOST_PROCESS_EXTENSIONS_HPP_
#include <boost/process/detail/handler.hpp>
+#include <boost/process/detail/used_handles.hpp>
#if defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/executor.hpp>
@@ -62,6 +63,9 @@ using ::boost::process::detail::api::async_handler;
using ::boost::process::detail::get_io_context;
using ::boost::process::detail::get_last_error;
using ::boost::process::detail::throw_last_error;
+using ::boost::process::detail::uses_handles;
+using ::boost::process::detail::foreach_used_handle;
+using ::boost::process::detail::get_used_handles;
///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;
diff --git a/boost/process/handles.hpp b/boost/process/handles.hpp
new file mode 100644
index 0000000000..23598f3108
--- /dev/null
+++ b/boost/process/handles.hpp
@@ -0,0 +1,107 @@
+// Copyright (c) 2019 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_HANDLES_HPP_
+#define BOOST_PROCESS_HANDLES_HPP_
+
+/**
+ * \file boost/process/handles.hpp
+ *
+ * Defines functions to obtain handles of the current process and limit the amount for inherited ones.
+ */
+
+#include <boost/process/detail/config.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/handles.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/handles.hpp>
+#endif
+
+#include <boost/process/detail/used_handles.hpp>
+
+
+namespace boost { namespace this_process
+{
+
+///The native type for handles
+using native_handle_type = ::boost::process::detail::api::native_handle_type;
+
+/**
+ * Get a snapshot of all handles of the process (i.e. file descriptors on posix and handles on windows) of the current process.
+ *
+ * \note This function might not work on certain posix systems.
+ *
+ * \note On Windows version older than windows 8 this function will iterate all the system handles, meaning it might be quite slow.
+ *
+ * \warning This functionality is utterly prone to race conditions, since other threads might open or close handles.
+ *
+ * \return The list of all open handles of the current process
+ */
+inline std::vector<native_handle_type> get_handles()
+{
+ return ::boost::process::detail::api::get_handles();
+}
+
+
+/** \overload std::vector<native_handle_type> get_handles() */
+inline std::vector<native_handle_type> get_handles(std::error_code &ec)
+{
+ return ::boost::process::detail::api::get_handles(ec);
+}
+
+/** Determines if a given handle is a a stream-handle, i.e. any handle that can be used with read and write functions.
+ * Stream handles include pipes, regular files and sockets.
+ *
+ * \return Indicates if it's a stream handle.
+ */
+inline bool is_stream_handle(native_handle_type handle)
+{
+ return ::boost::process::detail::api::is_stream_handle(handle);
+}
+
+
+/** \overload bool is_stream_handle(native_handle_type handle) */
+inline bool is_stream_handle(native_handle_type handle, std::error_code &ec)
+{
+ return ::boost::process::detail::api::is_stream_handle(handle, ec);
+}
+
+}
+namespace process
+{
+
+namespace detail
+{
+
+using limit_handles_ = ::boost::process::detail::api::limit_handles_;
+
+
+}
+
+/**
+ * The limit_handles property sets all properties to be inherited only expcitly. It closes all unused file-descriptors on posix after the fork and
+ * removes the inherit flags on windows.
+ *
+ * \note This is executed after the fork on posix.
+ *
+ * \code{.cpp}
+ * system("gcc", limit_handles);
+ * \endcode
+ *
+ * Since limit also closes the standard handles unless they are explicitly redirected they can be ignored by `limit_handles` in the following way.
+ *
+ * \code{.cpp}
+ * system("gcc", limit_handles.allowStd())
+ * \endcode
+ *
+*/
+const static ::boost::process::detail::api::limit_handles_ limit_handles;
+
+
+}
+}
+
+#endif //BOOST_PROCESS_HANDLES_HPP_
diff --git a/boost/process/pipe.hpp b/boost/process/pipe.hpp
index dd4af09d63..2040c78e3d 100644
--- a/boost/process/pipe.hpp
+++ b/boost/process/pipe.hpp
@@ -120,6 +120,13 @@ struct basic_pipebuf : std::basic_streambuf<CharT, Traits>
///Move Constructor
basic_pipebuf(basic_pipebuf && ) = default;
+ ///Destructor -> writes the frest of the data
+ ~basic_pipebuf()
+ {
+ if (is_open())
+ overflow(Traits::eof());
+ }
+
///Move construct from a pipe.
basic_pipebuf(pipe_type && p) : _pipe(std::move(p)),
_write(default_buffer_size),
@@ -155,7 +162,7 @@ struct basic_pipebuf : std::basic_streambuf<CharT, Traits>
///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 (_pipe.is_open() && (ch != traits_type::eof()))
{
if (this->pptr() == this->epptr())
{
@@ -173,6 +180,9 @@ struct basic_pipebuf : std::basic_streambuf<CharT, Traits>
return ch;
}
}
+ else if (ch == traits_type::eof())
+ this->sync();
+
return traits_type::eof();
}
///Synchronizes the buffers with the associated character sequence
@@ -212,6 +222,36 @@ struct basic_pipebuf : std::basic_streambuf<CharT, Traits>
const pipe_type &pipe() const & {return _pipe;}
///Get a rvalue reference to the pipe. Qualified as rvalue.
pipe_type && pipe() && {return std::move(_pipe);}
+
+ ///Check if the pipe is open
+ bool is_open() const {return _pipe.is_open(); }
+
+ ///Open a new pipe
+ basic_pipebuf<CharT, Traits>* open()
+ {
+ if (is_open())
+ return nullptr;
+ _pipe = pipe();
+ return this;
+ }
+
+ ///Open a new named pipe
+ basic_pipebuf<CharT, Traits>* open(const std::string & name)
+ {
+ if (is_open())
+ return nullptr;
+ _pipe = pipe(name);
+ return this;
+ }
+
+ ///Flush the buffer & close the pipe
+ basic_pipebuf<CharT, Traits>* close()
+ {
+ if (!is_open())
+ return nullptr;
+ overflow(Traits::eof());
+ return this;
+ }
private:
pipe_type _pipe;
std::vector<char_type> _write;
@@ -223,8 +263,13 @@ private:
return false;
auto base = this->pbase();
+
+ if (base == this->pptr())
+ return true;
+
std::ptrdiff_t wrt = _pipe.write(base,
static_cast<typename pipe_type::int_type>(this->pptr() - base));
+
std::ptrdiff_t diff = this->pptr() - base;
if (wrt < diff)
@@ -320,6 +365,33 @@ public:
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();}
+ ///Check if the pipe is open
+ bool is_open() const {return _buf->is_open();}
+
+ ///Open a new pipe
+ void open()
+ {
+ if (_buf.open() == nullptr)
+ this->setstate(std::ios_base::failbit);
+ else
+ this->clear();
+ }
+
+ ///Open a new named pipe
+ void open(const std::string & name)
+ {
+ if (_buf.open() == nullptr)
+ this->setstate(std::ios_base::failbit);
+ else
+ this->clear();
+ }
+
+ ///Flush the buffer & close the pipe
+ void close()
+ {
+ if (_buf.close() == nullptr)
+ this->setstate(std::ios_base::failbit);
+ }
};
typedef basic_ipstream<char> ipstream;
@@ -402,6 +474,31 @@ public:
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();}
+
+ ///Open a new pipe
+ void open()
+ {
+ if (_buf.open() == nullptr)
+ this->setstate(std::ios_base::failbit);
+ else
+ this->clear();
+ }
+
+ ///Open a new named pipe
+ void open(const std::string & name)
+ {
+ if (_buf.open() == nullptr)
+ this->setstate(std::ios_base::failbit);
+ else
+ this->clear();
+ }
+
+ ///Flush the buffer & close the pipe
+ void close()
+ {
+ if (_buf.close() == nullptr)
+ this->setstate(std::ios_base::failbit);
+ }
};
typedef basic_opstream<char> opstream;
@@ -484,6 +581,31 @@ public:
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();}
+
+ ///Open a new pipe
+ void open()
+ {
+ if (_buf.open() == nullptr)
+ this->setstate(std::ios_base::failbit);
+ else
+ this->clear();
+ }
+
+ ///Open a new named pipe
+ void open(const std::string & name)
+ {
+ if (_buf.open() == nullptr)
+ this->setstate(std::ios_base::failbit);
+ else
+ this->clear();
+ }
+
+ ///Flush the buffer & close the pipe
+ void close()
+ {
+ if (_buf.close() == nullptr)
+ this->setstate(std::ios_base::failbit);
+ }
};
typedef basic_pstream<char> pstream;
diff --git a/boost/proto/debug.hpp b/boost/proto/debug.hpp
index f732bc2a99..7d3e42fce0 100644
--- a/boost/proto/debug.hpp
+++ b/boost/proto/debug.hpp
@@ -11,14 +11,14 @@
#include <iostream>
#include <boost/preprocessor/stringize.hpp>
-#include <boost/ref.hpp>
+#include <boost/core/ref.hpp>
+#include <boost/core/typeinfo.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/proto/proto_fwd.hpp>
#include <boost/proto/traits.hpp>
#include <boost/proto/matches.hpp>
#include <boost/proto/fusion.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
-#include <boost/detail/sp_typeinfo.hpp>
namespace boost { namespace proto
{
@@ -100,7 +100,7 @@ namespace boost { namespace proto
{
template<typename T>
named_any(T const &)
- : name_(BOOST_SP_TYPEID(T).name())
+ : name_(BOOST_CORE_TYPEID(T).name())
{}
char const *name_;
@@ -114,6 +114,23 @@ namespace boost { namespace proto
namespace detail
{
+ // copyable functor to pass by value to fusion::foreach
+ struct display_expr_impl;
+ struct display_expr_impl_functor
+ {
+ display_expr_impl_functor(display_expr_impl const& impl): impl_(impl)
+ {}
+
+ template<typename Expr>
+ void operator()(Expr const &expr) const
+ {
+ this->impl_(expr);
+ }
+
+ private:
+ display_expr_impl const& impl_;
+ };
+
struct display_expr_impl
{
explicit display_expr_impl(std::ostream &sout, int depth = 0)
@@ -152,7 +169,7 @@ namespace boost { namespace proto
this->sout_ << (this->first_? "" : ", ");
this->sout_ << tag() << "(\n";
display_expr_impl display(this->sout_, this->depth_ + 4);
- fusion::for_each(expr, display);
+ fusion::for_each(expr, display_expr_impl_functor(display));
this->sout_.width(this->depth_);
this->sout_ << "" << ")\n";
this->first_ = false;
diff --git a/boost/proto/proto_fwd.hpp b/boost/proto/proto_fwd.hpp
index a1a25987f1..2078dfca77 100644
--- a/boost/proto/proto_fwd.hpp
+++ b/boost/proto/proto_fwd.hpp
@@ -683,7 +683,7 @@ namespace boost { namespace proto
typedef functional::make_pair _make_pair;
typedef functional::first _first;
typedef functional::second _second;
- typedef functional::pop_front _at;
+ typedef functional::at _at;
typedef functional::pop_front _pop_front;
typedef functional::push_front _push_front;
typedef functional::pop_back _pop_back;
diff --git a/boost/ptr_container/ptr_vector.hpp b/boost/ptr_container/ptr_vector.hpp
index d3ecdf88ec..944580bcf0 100644
--- a/boost/ptr_container/ptr_vector.hpp
+++ b/boost/ptr_container/ptr_vector.hpp
@@ -19,6 +19,8 @@
#include <vector>
#include <boost/ptr_container/ptr_sequence_adapter.hpp>
#include <boost/ptr_container/detail/ptr_container_disable_deprecated.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/mpl/if.hpp>
#if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED)
#pragma GCC diagnostic push
@@ -32,16 +34,27 @@ namespace boost
<
class T,
class CloneAllocator = heap_clone_allocator,
- class Allocator = std::allocator<typename ptr_container_detail::void_ptr<T>::type>
+ class Allocator = void
>
class ptr_vector : public
- ptr_sequence_adapter< T, std::vector<
- typename ptr_container_detail::void_ptr<T>::type,Allocator>,
- CloneAllocator >
+ ptr_sequence_adapter< T,
+ std::vector<
+ typename ptr_container_detail::void_ptr<T>::type,
+ typename boost::mpl::if_<boost::is_same<Allocator, void>,
+ std::allocator<typename ptr_container_detail::void_ptr<T>::type>, Allocator>::type
+ >,
+ CloneAllocator >
{
- typedef ptr_sequence_adapter< T, std::vector<
- typename ptr_container_detail::void_ptr<T>::type,Allocator>,
- CloneAllocator >
+ typedef
+
+ ptr_sequence_adapter< T,
+ std::vector<
+ typename ptr_container_detail::void_ptr<T>::type,
+ typename boost::mpl::if_<boost::is_same<Allocator, void>,
+ std::allocator<typename ptr_container_detail::void_ptr<T>::type>, Allocator>::type
+ >,
+ CloneAllocator >
+
base_class;
typedef ptr_vector<T,CloneAllocator,Allocator> this_type;
diff --git a/boost/qvm/quat_operations.hpp b/boost/qvm/quat_operations.hpp
index 1a4fdbf249..787473d312 100644
--- a/boost/qvm/quat_operations.hpp
+++ b/boost/qvm/quat_operations.hpp
@@ -1435,9 +1435,9 @@ boost
}
else
{
- typedef typename vec_traits<B>::scalar_type T;
- vec_traits<B>::template write_element<0>(b) = scalar_traits<T>::value(1);
- vec_traits<B>::template write_element<1>(b) = vec_traits<B>::template write_element<2>(b) = scalar_traits<T>::value(0);
+ typedef typename vec_traits<B>::scalar_type U;
+ vec_traits<B>::template write_element<0>(b) = scalar_traits<U>::value(1);
+ vec_traits<B>::template write_element<1>(b) = vec_traits<B>::template write_element<2>(b) = scalar_traits<U>::value(0);
}
return scalar_traits<T>::value(2) * qvm::acos(a0);
}
diff --git a/boost/range/algorithm/max_element.hpp b/boost/range/algorithm/max_element.hpp
index dd2b9cb8b3..50669b37dd 100644
--- a/boost/range/algorithm/max_element.hpp
+++ b/boost/range/algorithm/max_element.hpp
@@ -3,17 +3,18 @@
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
+// Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com)
//
// For more information, see http://www.boost.org/libs/range/
//
#ifndef BOOST_RANGE_ALGORITHM_MAX_ELEMENT_HPP_INCLUDED
#define BOOST_RANGE_ALGORITHM_MAX_ELEMENT_HPP_INCLUDED
-#include <boost/algorithm/minmax_element.hpp>
#include <boost/concept_check.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/concepts.hpp>
+#include <boost/range/detail/less.hpp>
#include <boost/range/detail/range_return.hpp>
namespace boost
@@ -21,6 +22,27 @@ namespace boost
namespace range
{
+namespace detail
+{
+
+template<typename Iterator, class Predicate>
+inline Iterator
+max_element(Iterator first, Iterator last, Predicate comp)
+{
+ if (first == last) {
+ return last;
+ }
+ Iterator result = first;
+ while (++first != last) {
+ if (comp(*result, *first)) {
+ result = first;
+ }
+ }
+ return result;
+}
+
+} // namespace detail
+
/// \brief template function max_element
///
/// range-based version of the max_element std algorithm
@@ -32,7 +54,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
max_element(ForwardRange& rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> ));
- return boost::first_max_element(boost::begin(rng), boost::end(rng));
+ return detail::max_element(boost::begin(rng), boost::end(rng), detail::less());
}
/// \overload
@@ -41,7 +63,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
max_element(const ForwardRange& rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> ));
- return boost::first_max_element(boost::begin(rng), boost::end(rng));
+ return detail::max_element(boost::begin(rng), boost::end(rng), detail::less());
}
/// \overload
@@ -50,7 +72,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
max_element(ForwardRange& rng, BinaryPredicate pred)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> ));
- return boost::first_max_element(boost::begin(rng), boost::end(rng), pred);
+ return detail::max_element(boost::begin(rng), boost::end(rng), pred);
}
/// \overload
@@ -59,7 +81,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
max_element(const ForwardRange& rng, BinaryPredicate pred)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> ));
- return boost::first_max_element(boost::begin(rng), boost::end(rng), pred);
+ return detail::max_element(boost::begin(rng), boost::end(rng), pred);
}
// range_return overloads
@@ -71,7 +93,7 @@ max_element(ForwardRange& rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> ));
return range_return<ForwardRange,re>::pack(
- boost::first_max_element(boost::begin(rng), boost::end(rng)),
+ detail::max_element(boost::begin(rng), boost::end(rng), detail::less()),
rng);
}
@@ -82,7 +104,7 @@ max_element(const ForwardRange& rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> ));
return range_return<const ForwardRange,re>::pack(
- boost::first_max_element(boost::begin(rng), boost::end(rng)),
+ detail::max_element(boost::begin(rng), boost::end(rng), detail::less()),
rng);
}
@@ -93,7 +115,7 @@ max_element(ForwardRange& rng, BinaryPredicate pred)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> ));
return range_return<ForwardRange,re>::pack(
- boost::first_max_element(boost::begin(rng), boost::end(rng), pred),
+ detail::max_element(boost::begin(rng), boost::end(rng), pred),
rng);
}
@@ -104,7 +126,7 @@ max_element(const ForwardRange& rng, BinaryPredicate pred)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> ));
return range_return<const ForwardRange,re>::pack(
- boost::first_max_element(boost::begin(rng), boost::end(rng), pred),
+ detail::max_element(boost::begin(rng), boost::end(rng), pred),
rng);
}
diff --git a/boost/range/algorithm/min_element.hpp b/boost/range/algorithm/min_element.hpp
index 339f56a93c..764de8b209 100644
--- a/boost/range/algorithm/min_element.hpp
+++ b/boost/range/algorithm/min_element.hpp
@@ -3,17 +3,18 @@
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
+// Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com)
//
// For more information, see http://www.boost.org/libs/range/
//
#ifndef BOOST_RANGE_ALGORITHM_MIN_ELEMENT_HPP_INCLUDED
#define BOOST_RANGE_ALGORITHM_MIN_ELEMENT_HPP_INCLUDED
-#include <boost/algorithm/minmax_element.hpp>
#include <boost/concept_check.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/concepts.hpp>
+#include <boost/range/detail/less.hpp>
#include <boost/range/detail/range_return.hpp>
namespace boost
@@ -21,6 +22,27 @@ namespace boost
namespace range
{
+namespace detail
+{
+
+template<typename Iterator, class Predicate>
+inline Iterator
+min_element(Iterator first, Iterator last, Predicate comp)
+{
+ if (first == last) {
+ return last;
+ }
+ Iterator result = first;
+ while (++first != last) {
+ if (comp(*first, *result)) {
+ result = first;
+ }
+ }
+ return result;
+}
+
+} // namespace detail
+
/// \brief template function min_element
///
/// range-based version of the min_element std algorithm
@@ -32,7 +54,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
min_element(ForwardRange& rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> ));
- return boost::first_min_element(boost::begin(rng), boost::end(rng));
+ return detail::min_element(boost::begin(rng), boost::end(rng), detail::less());
}
/// \overload
@@ -41,7 +63,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
min_element(const ForwardRange& rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> ));
- return boost::first_min_element(boost::begin(rng), boost::end(rng));
+ return detail::min_element(boost::begin(rng), boost::end(rng), detail::less());
}
/// \overload
@@ -50,7 +72,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
min_element(ForwardRange& rng, BinaryPredicate pred)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> ));
- return boost::first_min_element(boost::begin(rng), boost::end(rng), pred);
+ return detail::min_element(boost::begin(rng), boost::end(rng), pred);
}
/// \overload
@@ -59,7 +81,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
min_element(const ForwardRange& rng, BinaryPredicate pred)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> ));
- return boost::first_min_element(boost::begin(rng), boost::end(rng), pred);
+ return detail::min_element(boost::begin(rng), boost::end(rng), pred);
}
// range_return overloads
@@ -71,7 +93,7 @@ min_element(ForwardRange& rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> ));
return range_return<ForwardRange,re>::pack(
- boost::first_min_element(boost::begin(rng), boost::end(rng)),
+ detail::min_element(boost::begin(rng), boost::end(rng), detail::less()),
rng);
}
@@ -82,7 +104,7 @@ min_element(const ForwardRange& rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> ));
return range_return<const ForwardRange,re>::pack(
- boost::first_min_element(boost::begin(rng), boost::end(rng)),
+ detail::min_element(boost::begin(rng), boost::end(rng), detail::less()),
rng);
}
@@ -93,7 +115,7 @@ min_element(ForwardRange& rng, BinaryPredicate pred)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> ));
return range_return<ForwardRange,re>::pack(
- boost::first_min_element(boost::begin(rng), boost::end(rng), pred),
+ detail::min_element(boost::begin(rng), boost::end(rng), pred),
rng);
}
@@ -104,7 +126,7 @@ min_element(const ForwardRange& rng, BinaryPredicate pred)
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> ));
return range_return<const ForwardRange,re>::pack(
- boost::first_min_element(boost::begin(rng), boost::end(rng), pred),
+ detail::min_element(boost::begin(rng), boost::end(rng), pred),
rng);
}
diff --git a/boost/range/detail/less.hpp b/boost/range/detail/less.hpp
new file mode 100644
index 0000000000..957c5b6f65
--- /dev/null
+++ b/boost/range/detail/less.hpp
@@ -0,0 +1,26 @@
+/*
+Copyright 2019 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_RANGE_DETAIL_LESS
+#define BOOST_RANGE_DETAIL_LESS
+
+namespace boost {
+namespace range {
+namespace detail {
+
+struct less {
+ template<class T, class U>
+ bool operator()(const T& lhs, const U& rhs) const {
+ return lhs < rhs;
+ }
+};
+
+} /* detail */
+} /* range */
+} /* boost */
+
+#endif
diff --git a/boost/rational.hpp b/boost/rational.hpp
index 8cd70b3e22..f33bc3b1f8 100644
--- a/boost/rational.hpp
+++ b/boost/rational.hpp
@@ -87,6 +87,7 @@
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_array.hpp>
// Control whether depreciated GCD and LCM functions are included (default: yes)
#ifndef BOOST_CONTROL_RATIONAL_HAS_GCD
@@ -113,8 +114,11 @@ IntType lcm(IntType n, IntType m)
namespace rational_detail{
+ template <class FromInt, class ToInt, typename Enable = void>
+ struct is_compatible_integer;
+
template <class FromInt, class ToInt>
- struct is_compatible_integer
+ struct is_compatible_integer<FromInt, ToInt, typename enable_if_c<!is_array<FromInt>::value>::type>
{
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)
@@ -125,6 +129,29 @@ namespace rational_detail{
|| (is_class<ToInt>::value && is_class<FromInt>::value && is_convertible<FromInt, ToInt>::value));
};
+ template <class FromInt, class ToInt>
+ struct is_compatible_integer<FromInt, ToInt, typename enable_if_c<is_array<FromInt>::value>::type>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ };
+
+ template <class FromInt, class ToInt, typename Enable = void>
+ struct is_backward_compatible_integer;
+
+ template <class FromInt, class ToInt>
+ struct is_backward_compatible_integer<FromInt, ToInt, typename enable_if_c<!is_array<FromInt>::value>::type>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = (std::numeric_limits<FromInt>::is_specialized && std::numeric_limits<FromInt>::is_integer
+ && !is_compatible_integer<FromInt, ToInt>::value
+ && (std::numeric_limits<FromInt>::radix == std::numeric_limits<ToInt>::radix)
+ && is_convertible<FromInt, ToInt>::value));
+ };
+
+ template <class FromInt, class ToInt>
+ struct is_backward_compatible_integer<FromInt, ToInt, typename enable_if_c<is_array<FromInt>::value>::type>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ };
}
class bad_rational : public std::domain_error
@@ -152,10 +179,12 @@ public:
BOOST_CONSTEXPR
rational() : num(0), den(1) {}
- template <class T>
+
+ template <class T>//, typename enable_if_c<!is_array<T>::value>::type>
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>
BOOST_CXX14_CONSTEXPR 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
@@ -200,12 +229,9 @@ public:
// 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>
+ template <class T>//, typename enable_if_c<!is_array<T>::value>::type>
BOOST_CXX14_CONSTEXPR 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
+ rational_detail::is_backward_compatible_integer<T, IntType>::value
>::type const* = 0)
{
assign(n, static_cast<T>(1));
diff --git a/boost/safe_numerics/checked_float.hpp b/boost/safe_numerics/checked_float.hpp
index 696c14c52b..696af9a5b0 100644
--- a/boost/safe_numerics/checked_float.hpp
+++ b/boost/safe_numerics/checked_float.hpp
@@ -21,7 +21,7 @@ namespace checked {
////////////////////////////////////////////////////
// layer 0 - implement safe operations for floating
-template<typename R, typename T>
+template<typename R, typename T, class F>
struct heterogeneous_checked_operation<R, T, F,
typename std::enable_if<
std::is_floating_point<R>::value
@@ -34,20 +34,41 @@ struct heterogeneous_checked_operation<R, T, F,
};
}; // checked_unary_operation
+template<typename R, typename T, class F>
+struct heterogeneous_checked_operation<R, T, F,
+ typename std::enable_if<
+ std::is_floating_point<R>::value
+ && std::is_integralt<T>::value
+ >::type
+>{
+ constexpr static checked_result<R>
+ cast(const T & t) noexcept {
+ return t;
+ };
+}; // checked_unary_operation
+
template<typename R, typename T, typename U>
struct checked_operation<R, T, U, F,
typename std::enable_if<
std::is_floating_point<R>::value
>::type
>{
- constexpr static checked_result<R> add(const T & t, const U & u) noexcept {
+ constexpr static checked_result<R> cast(const T & t) {
+ return
+ cast_impl_detail::cast_impl(
+ t,
+ std::is_signed<R>(),
+ std::is_signed<T>()
+ );
+ }
+ constexpr static checked_result<R> add(const T & t, const U & u) {
return t + u;
}
constexpr static checked_result<R> subtract(
const T & t,
const U & u
- ) noexcept {
+ ) {
return t - u;
}
diff --git a/boost/safe_numerics/exception.hpp b/boost/safe_numerics/exception.hpp
index 284b801d09..470d9d2991 100644
--- a/boost/safe_numerics/exception.hpp
+++ b/boost/safe_numerics/exception.hpp
@@ -98,7 +98,7 @@ public:
} safe_numerics_error_category {};
// constexpr - damn, can't use constexpr due to std::error_code
-std::error_code make_error_code(const safe_numerics_error & e){
+inline std::error_code make_error_code(const safe_numerics_error & e){
return std::error_code(static_cast<int>(e), safe_numerics_error_category);
}
diff --git a/boost/safe_numerics/safe_base_operations.hpp b/boost/safe_numerics/safe_base_operations.hpp
index 982358208a..fb8f31073f 100644
--- a/boost/safe_numerics/safe_base_operations.hpp
+++ b/boost/safe_numerics/safe_base_operations.hpp
@@ -20,7 +20,6 @@
#include "checked_integer.hpp"
#include "checked_result.hpp"
-#include "checked_result_operations.hpp"
#include "safe_base.hpp"
#include "interval.hpp"
diff --git a/boost/safe_numerics/safe_integer.hpp b/boost/safe_numerics/safe_integer.hpp
index 56281f36cf..a6f1983dbd 100644
--- a/boost/safe_numerics/safe_integer.hpp
+++ b/boost/safe_numerics/safe_integer.hpp
@@ -10,6 +10,7 @@
// not actually used here - but needed for integer arithmetic
// so this is a good place to include it
#include "checked_integer.hpp"
+#include "checked_result_operations.hpp"
#include "safe_base.hpp"
#include "safe_base_operations.hpp"
diff --git a/boost/safe_numerics/utility.hpp b/boost/safe_numerics/utility.hpp
index 79a439acc9..c0cc2dd5df 100644
--- a/boost/safe_numerics/utility.hpp
+++ b/boost/safe_numerics/utility.hpp
@@ -23,12 +23,19 @@ namespace utility {
///////////////////////////////////////////////////////////////////////////////
// used for debugging
-// usage - print_type<T>;
-// provokes error message with name of type T
+// provokes warning message with names of type T
+// usage - print_types<T, ...>;
+// see https://cukic.co/2019/02/19/tmp-testing-and-debugging-templates
+/*
template<typename Tx>
using print_type = typename Tx::error_message;
+*/
+template <typename... Ts>
+struct [[deprecated]] print_types {};
+// display value of constexpr during compilation
+// usage print_value(N) pn;
template<int N>
struct print_value
{
@@ -37,6 +44,25 @@ struct print_value
};
};
+#if 0
+// static warning - same as static_assert but doesn't
+// stop compilation.
+template <typename T>
+struct static_test{};
+
+template <>
+struct static_test<std::false_type>{
+ [[deprecated]] static_test(){}
+};
+
+template<typename T>
+constexpr void static_warning(const T){
+ //using x = static_test<T>;
+ const static_test<T> x;
+}
+
+#endif
+
/*
// can be called by constexpr to produce a compile time
// trap of parameter passed is false.
diff --git a/boost/signals2/detail/auto_buffer.hpp b/boost/signals2/detail/auto_buffer.hpp
index 5ff8dd2c63..9ee9a5cf36 100644
--- a/boost/signals2/detail/auto_buffer.hpp
+++ b/boost/signals2/detail/auto_buffer.hpp
@@ -21,7 +21,7 @@
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/mpl/if.hpp>
-#include <boost/multi_index/detail/scope_guard.hpp>
+#include <boost/signals2/detail/scope_guard.hpp>
#include <boost/swap.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
@@ -288,11 +288,10 @@ namespace detail
pointer move_to_new_buffer( size_type new_capacity, const boost::false_type& )
{
pointer new_buffer = allocate( new_capacity ); // strong
- boost::multi_index::detail::scope_guard guard =
- boost::multi_index::detail::make_obj_guard( *this,
- &auto_buffer::deallocate,
- new_buffer,
- new_capacity );
+ scope_guard guard = make_obj_guard( *this,
+ &auto_buffer::deallocate,
+ new_buffer,
+ new_capacity );
copy_impl( begin(), end(), new_buffer ); // strong
guard.dismiss(); // nothrow
return new_buffer;
@@ -517,11 +516,10 @@ namespace detail
auto_buffer_destroy();
buffer_ = 0;
pointer new_buffer = allocate( r.size() );
- boost::multi_index::detail::scope_guard guard =
- boost::multi_index::detail::make_obj_guard( *this,
- &auto_buffer::deallocate,
- new_buffer,
- r.size() );
+ scope_guard guard = make_obj_guard( *this,
+ &auto_buffer::deallocate,
+ new_buffer,
+ r.size() );
copy_impl( r.begin(), r.end(), new_buffer );
guard.dismiss();
buffer_ = new_buffer;
diff --git a/boost/signals2/detail/scope_guard.hpp b/boost/signals2/detail/scope_guard.hpp
new file mode 100644
index 0000000000..a0222045f7
--- /dev/null
+++ b/boost/signals2/detail/scope_guard.hpp
@@ -0,0 +1,110 @@
+/* Copyright 2003-2013 Joaquin M Lopez Munoz.
+ * 2019 Mike Dev <mike.dev@gmx.de>
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * NOTE: internalized from Boost.MultiIndex
+ *
+ */
+
+
+#ifndef BOOST_SIGNALS2_DETAIL_SCOPE_GUARD_HPP
+#define BOOST_SIGNALS2_DETAIL_SCOPE_GUARD_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/core/no_exceptions_support.hpp>
+
+namespace boost{
+
+namespace signals2{
+
+namespace detail{
+
+/* This is a merely reformated version of
+ * ScopeGuard.h as defined in:
+ * Alexandrescu, A., Marginean, P.:"Generic<Programming>: Change the Way You
+ * Write Exception-Safe Code - Forever", C/C++ Users Jornal, Dec 2000,
+ * http://www.drdobbs.com/184403758
+ * with the following modifications:
+ * - General pretty formatting (pretty to my taste at least.)
+ * - Naming style changed to standard C++ library requirements.
+ * - Removed RefHolder and ByRef, whose functionality is provided
+ * already by Boost.Ref.
+ * - Removed static make_guard's and make_obj_guard's, so that the code
+ * will work even if BOOST_NO_MEMBER_TEMPLATES is defined. This forces
+ * us to move some private ctors to public, though.
+ *
+ * NB: CodeWarrior Pro 8 seems to have problems looking up safe_execute
+ * without an explicit qualification.
+ *
+ * TODO: Consider replacing with Boost.ScopeExit
+ *
+ */
+
+class scope_guard_impl_base
+{
+public:
+ scope_guard_impl_base():dismissed_(false){}
+ void dismiss()const{dismissed_=true;}
+
+protected:
+ ~scope_guard_impl_base(){}
+
+ scope_guard_impl_base(const scope_guard_impl_base& other):
+ dismissed_(other.dismissed_)
+ {
+ other.dismiss();
+ }
+
+ template<typename J>
+ static void safe_execute(J& j){
+ BOOST_TRY{
+ if(!j.dismissed_)j.execute();
+ }
+ BOOST_CATCH(...){}
+ BOOST_CATCH_END
+ }
+
+ mutable bool dismissed_;
+
+private:
+ scope_guard_impl_base& operator=(const scope_guard_impl_base&);
+};
+
+typedef const scope_guard_impl_base& scope_guard;
+
+template<class Obj,typename MemFun,typename P1,typename P2>
+class obj_scope_guard_impl2:public scope_guard_impl_base
+{
+public:
+ obj_scope_guard_impl2(Obj& obj,MemFun mem_fun,P1 p1,P2 p2):
+ obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2)
+ {}
+ ~obj_scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);}
+ void execute(){(obj_.*mem_fun_)(p1_,p2_);}
+
+protected:
+ Obj& obj_;
+ MemFun mem_fun_;
+ const P1 p1_;
+ const P2 p2_;
+};
+
+template<class Obj,typename MemFun,typename P1,typename P2>
+inline obj_scope_guard_impl2<Obj,MemFun,P1,P2>
+make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
+{
+ return obj_scope_guard_impl2<Obj,MemFun,P1,P2>(obj,mem_fun,p1,p2);
+}
+
+} /* namespace signals2::detail */
+
+} /* namespace signals2 */
+
+} /* namespace boost */
+
+#endif
diff --git a/boost/signals2/detail/signal_template.hpp b/boost/signals2/detail/signal_template.hpp
index b92a143ade..c7fb253562 100644
--- a/boost/signals2/detail/signal_template.hpp
+++ b/boost/signals2/detail/signal_template.hpp
@@ -658,7 +658,7 @@ namespace boost
BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const combiner_type &combiner_arg = combiner_type(),
const group_compare_type &group_compare = group_compare_type()):
_pimpl(new impl_class(combiner_arg, group_compare))
- {};
+ {}
virtual ~BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)()
{
}
@@ -670,7 +670,7 @@ namespace boost
{
using std::swap;
swap(_pimpl, other._pimpl);
- };
+ }
BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) &
operator=(BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) && rhs)
diff --git a/boost/signals2/detail/slot_call_iterator.hpp b/boost/signals2/detail/slot_call_iterator.hpp
index 769f6c222d..c9660790ef 100644
--- a/boost/signals2/detail/slot_call_iterator.hpp
+++ b/boost/signals2/detail/slot_call_iterator.hpp
@@ -149,21 +149,11 @@ namespace boost {
{
return;
}
- if(iter == end)
- {
- if(callable_iter != end)
- {
- lock_type lock(**callable_iter);
- set_callable_iter(lock, end);
- return;
- }
- }
- // we're only locking the first connection body,
- // but it doesn't matter they all use the same mutex
- lock_type lock(**iter);
+
for(;iter != end; ++iter)
{
cache->tracked_ptrs.clear();
+ lock_type lock(**iter);
(*iter)->nolock_grab_tracked_objects(lock, std::back_inserter(cache->tracked_ptrs));
if((*iter)->nolock_nograb_connected())
{
@@ -178,9 +168,14 @@ namespace boost {
break;
}
}
+
if(iter == end)
{
- set_callable_iter(lock, end);
+ if(callable_iter != end)
+ {
+ lock_type lock(**callable_iter);
+ set_callable_iter(lock, end);
+ }
}
}
diff --git a/boost/signals2/signal_type.hpp b/boost/signals2/signal_type.hpp
index 4de5396fe2..fe1b1b7b3a 100644
--- a/boost/signals2/signal_type.hpp
+++ b/boost/signals2/signal_type.hpp
@@ -17,21 +17,21 @@
#ifndef BOOST_SIGNALS2_SIGNAL_TYPE_HPP
#define BOOST_SIGNALS2_SIGNAL_TYPE_HPP
-// support for function types is currently broken in Boost.Parameter
-// #define BOOST_SIGNALS2_NAMED_SIGNATURE_PARAMETER
+#include <boost/parameter/config.hpp>
-#include <boost/signals2/signal.hpp>
-
-#if !defined(BOOST_PARAMETER_MAX_ARITY)
-#define BOOST_PARAMETER_MAX_ARITY 7
-#else
#if BOOST_PARAMETER_MAX_ARITY < 7
-#error This header requires BOOST_PARAMETER_MAX_ARITY to be defined as 7 or greater prior to including Boost.Parameter headers
-#endif // BOOST_PARAMETER_MAX_ARITY < 7
-#endif // !defined(BOOST_PARAMETER_MAX_ARITY)
-#include <boost/parameter.hpp>
+#error Define BOOST_PARAMETER_MAX_ARITY as 7 or greater.
+#endif
+#include <boost/parameter/template_keyword.hpp>
+#include <boost/parameter/parameters.hpp>
+#include <boost/parameter/required.hpp>
+#include <boost/parameter/optional.hpp>
+#include <boost/parameter/value_type.hpp>
#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/function_traits.hpp>
+#include <boost/signals2/signal.hpp>
+#include <functional>
namespace boost
{
@@ -39,9 +39,7 @@ namespace boost
{
namespace keywords
{
-#ifdef BOOST_SIGNALS2_NAMED_SIGNATURE_PARAMETER
BOOST_PARAMETER_TEMPLATE_KEYWORD(signature_type)
-#endif
BOOST_PARAMETER_TEMPLATE_KEYWORD(combiner_type)
BOOST_PARAMETER_TEMPLATE_KEYWORD(group_type)
BOOST_PARAMETER_TEMPLATE_KEYWORD(group_compare_type)
@@ -51,11 +49,7 @@ namespace boost
} // namespace keywords
template <
-#ifdef BOOST_SIGNALS2_NAMED_SIGNATURE_PARAMETER
typename A0,
-#else
- typename Signature,
-#endif
typename A1 = parameter::void_,
typename A2 = parameter::void_,
typename A3 = parameter::void_,
@@ -66,9 +60,7 @@ namespace boost
class signal_type
{
typedef parameter::parameters<
-#ifdef BOOST_SIGNALS2_NAMED_SIGNATURE_PARAMETER
parameter::required<keywords::tag::signature_type, is_function<boost::mpl::_> >,
-#endif
parameter::optional<keywords::tag::combiner_type>,
parameter::optional<keywords::tag::group_type>,
parameter::optional<keywords::tag::group_compare_type>,
@@ -79,20 +71,11 @@ namespace boost
public:
// ArgumentPack
- typedef typename
- parameter_spec::bind<
-#ifdef BOOST_SIGNALS2_NAMED_SIGNATURE_PARAMETER
- A0,
-#endif
- A1, A2, A3, A4, A5, A6>::type
+ typedef typename parameter_spec::bind<A0, A1, A2, A3, A4, A5, A6>::type
args;
-#ifdef BOOST_SIGNALS2_NAMED_SIGNATURE_PARAMETER
typedef typename parameter::value_type<args, keywords::tag::signature_type>::type
signature_type;
-#else
- typedef Signature signature_type;
-#endif
typedef typename parameter::value_type
<
diff --git a/boost/smart_ptr/allocate_local_shared_array.hpp b/boost/smart_ptr/allocate_local_shared_array.hpp
index c1c7373738..0890849134 100644
--- a/boost/smart_ptr/allocate_local_shared_array.hpp
+++ b/boost/smart_ptr/allocate_local_shared_array.hpp
@@ -72,21 +72,19 @@ inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator, std::size_t count)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef typename detail::sp_array_element<T>::type element;
+ typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state> base;
- std::size_t size = count * detail::sp_array_count<type, scalar>::value;
- detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(allocator, size, start);
+ element* start = detail::sp_array_start<element>(node);
+ ::new(static_cast<void*>(node)) base(allocator, start, count);
detail::lsp_array_base& local = node->state().base();
local.set(node);
result.release();
- return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), &local);
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
+ &local);
}
template<class T, class A>
@@ -94,23 +92,22 @@ inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
- size = detail::sp_array_count<T, scalar>::value
+ count = extent<T>::value
};
- typedef detail::lsp_size_array_state<other, size> state;
+ typedef typename detail::sp_array_element<T>::type element;
+ typedef typename detail::sp_bind_allocator<A, element>::type other;
+ typedef detail::lsp_size_array_state<other, count> state;
typedef detail::sp_array_base<state> base;
- detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(allocator, size, start);
+ element* start = detail::sp_array_start<element>(node);
+ ::new(static_cast<void*>(node)) base(allocator, start, count);
detail::lsp_array_base& local = node->state().base();
local.set(node);
result.release();
- return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), &local);
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
+ &local);
}
template<class T, class A>
@@ -119,25 +116,19 @@ inline typename enable_if_<is_unbounded_array<T>::value,
allocate_local_shared(const A& allocator, std::size_t count,
const typename remove_extent<T>::type& value)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef typename detail::sp_array_element<T>::type element;
+ typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state> base;
- enum {
- total = detail::sp_array_count<type, scalar>::value
- };
- std::size_t size = count * total;
- detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(allocator, size,
- reinterpret_cast<const scalar*>(&value), total, start);
+ element* start = detail::sp_array_start<element>(node);
+ ::new(static_cast<void*>(node)) base(allocator, start, count, value);
detail::lsp_array_base& local = node->state().base();
local.set(node);
result.release();
- return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), &local);
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
+ &local);
}
template<class T, class A>
@@ -146,25 +137,22 @@ inline typename enable_if_<is_bounded_array<T>::value,
allocate_local_shared(const A& allocator,
const typename remove_extent<T>::type& value)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
- size = detail::sp_array_count<T, scalar>::value
+ count = extent<T>::value
};
- typedef detail::lsp_size_array_state<other, size> state;
+ typedef typename detail::sp_array_element<T>::type element;
+ typedef typename detail::sp_bind_allocator<A, element>::type other;
+ typedef detail::lsp_size_array_state<other, count> state;
typedef detail::sp_array_base<state> base;
- detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(allocator, size,
- reinterpret_cast<const scalar*>(&value),
- detail::sp_array_count<type, scalar>::value, start);
+ element* start = detail::sp_array_start<element>(node);
+ ::new(static_cast<void*>(node)) base(allocator, start, count, value);
detail::lsp_array_base& local = node->state().base();
local.set(node);
result.release();
- return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), &local);
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
+ &local);
}
template<class T, class A>
@@ -172,22 +160,8 @@ inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared_noinit(const A& allocator, std::size_t count)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
- typedef detail::lsp_array_state<other> state;
- typedef detail::sp_array_base<state, false> base;
- std::size_t size = count * detail::sp_array_count<type, scalar>::value;
- detail::sp_array_result<other, base> result(allocator, size);
- base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
- size, start);
- detail::lsp_array_base& local = node->state().base();
- local.set(node);
- result.release();
- return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), &local);
+ return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator),
+ count);
}
template<class T, class A>
@@ -195,24 +169,7 @@ inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared_noinit(const A& allocator)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
- enum {
- size = detail::sp_array_count<T, scalar>::value
- };
- typedef detail::lsp_size_array_state<other, size> state;
- typedef detail::sp_array_base<state, false> base;
- detail::sp_array_result<other, base> result(allocator, size);
- base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
- size, start);
- detail::lsp_array_base& local = node->state().base();
- local.set(node);
- result.release();
- return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), &local);
+ return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator));
}
} /* boost */
diff --git a/boost/smart_ptr/allocate_shared_array.hpp b/boost/smart_ptr/allocate_shared_array.hpp
index 5aab81abdb..bca98650d7 100644
--- a/boost/smart_ptr/allocate_shared_array.hpp
+++ b/boost/smart_ptr/allocate_shared_array.hpp
@@ -8,15 +8,14 @@ Distributed under the Boost Software License, Version 1.0.
#ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
+#include <boost/core/alloc_construct.hpp>
+#include <boost/core/first_scalar.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/enable_if.hpp>
+#include <boost/type_traits/extent.hpp>
#include <boost/type_traits/is_bounded_array.hpp>
#include <boost/type_traits/is_unbounded_array.hpp>
-#include <boost/type_traits/has_trivial_assign.hpp>
-#include <boost/type_traits/has_trivial_constructor.hpp>
-#include <boost/type_traits/has_trivial_destructor.hpp>
-#include <boost/type_traits/remove_all_extents.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
@@ -25,15 +24,22 @@ namespace boost {
namespace detail {
template<class T>
-struct sp_array_scalar {
+struct sp_array_element {
typedef typename boost::remove_cv<typename
- boost::remove_all_extents<T>::type>::type type;
+ boost::remove_extent<T>::type>::type type;
};
-template<class T, class U>
+template<class T>
struct sp_array_count {
enum {
- value = sizeof(T) / sizeof(U)
+ value = 1
+ };
+};
+
+template<class T, std::size_t N>
+struct sp_array_count<T[N]> {
+ enum {
+ value = N * sp_array_count<T>::value
};
};
@@ -70,154 +76,6 @@ sp_objects(std::size_t size) BOOST_SP_NOEXCEPT
return (size + sizeof(T) - 1) / sizeof(T);
}
-template<bool E, class A, class T>
-inline typename boost::enable_if_<!E &&
- boost::has_trivial_destructor<T>::value>::type
-sp_array_destroy(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
-
-template<bool E, class A, class T>
-inline typename boost::enable_if_<!E &&
- !boost::has_trivial_destructor<T>::value>::type
-sp_array_destroy(A&, T* ptr, std::size_t size)
-{
- while (size > 0) {
- ptr[--size].~T();
- }
-}
-
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-template<bool E, class A, class T>
-inline typename boost::enable_if_<E>::type
-sp_array_destroy(A& allocator, T* ptr, std::size_t size)
-{
- while (size > 0) {
- std::allocator_traits<A>::destroy(allocator, ptr + --size);
- }
-}
-#endif
-
-template<bool E, class A, class T>
-class sp_destroyer {
-public:
- sp_destroyer(A& allocator, T* ptr) BOOST_SP_NOEXCEPT
- : allocator_(allocator),
- ptr_(ptr),
- size_(0) { }
-
- ~sp_destroyer() {
- sp_array_destroy<E>(allocator_, ptr_, size_);
- }
-
- std::size_t& size() BOOST_SP_NOEXCEPT {
- return size_;
- }
-
-private:
- sp_destroyer(const sp_destroyer&);
- sp_destroyer& operator=(const sp_destroyer&);
-
- A& allocator_;
- T* ptr_;
- std::size_t size_;
-};
-
-template<bool E, class A, class T>
-inline typename boost::enable_if_<!E &&
- boost::has_trivial_constructor<T>::value &&
- boost::has_trivial_assign<T>::value &&
- boost::has_trivial_destructor<T>::value>::type
-sp_array_construct(A&, T* ptr, std::size_t size)
-{
- for (std::size_t i = 0; i < size; ++i) {
- ptr[i] = T();
- }
-}
-
-template<bool E, class A, class T>
-inline typename boost::enable_if_<!E &&
- boost::has_trivial_constructor<T>::value &&
- boost::has_trivial_assign<T>::value &&
- boost::has_trivial_destructor<T>::value>::type
-sp_array_construct(A&, T* ptr, std::size_t size, const T* list,
- std::size_t count)
-{
- for (std::size_t i = 0; i < size; ++i) {
- ptr[i] = list[i % count];
- }
-}
-
-template<bool E, class A, class T>
-inline typename boost::enable_if_<!E &&
- !(boost::has_trivial_constructor<T>::value &&
- boost::has_trivial_assign<T>::value &&
- boost::has_trivial_destructor<T>::value)>::type
-sp_array_construct(A& none, T* ptr, std::size_t size)
-{
- sp_destroyer<E, A, T> hold(none, ptr);
- for (std::size_t& i = hold.size(); i < size; ++i) {
- ::new(static_cast<void*>(ptr + i)) T();
- }
- hold.size() = 0;
-}
-
-template<bool E, class A, class T>
-inline typename boost::enable_if_<!E &&
- !(boost::has_trivial_constructor<T>::value &&
- boost::has_trivial_assign<T>::value &&
- boost::has_trivial_destructor<T>::value)>::type
-sp_array_construct(A& none, T* ptr, std::size_t size, const T* list,
- std::size_t count)
-{
- sp_destroyer<E, A, T> hold(none, ptr);
- for (std::size_t& i = hold.size(); i < size; ++i) {
- ::new(static_cast<void*>(ptr + i)) T(list[i % count]);
- }
- hold.size() = 0;
-}
-
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-template<bool E, class A, class T>
-inline typename boost::enable_if_<E>::type
-sp_array_construct(A& allocator, T* ptr, std::size_t size)
-{
- sp_destroyer<E, A, T> hold(allocator, ptr);
- for (std::size_t& i = hold.size(); i < size; ++i) {
- std::allocator_traits<A>::construct(allocator, ptr + i);
- }
- hold.size() = 0;
-}
-
-template<bool E, class A, class T>
-inline typename boost::enable_if_<E>::type
-sp_array_construct(A& allocator, T* ptr, std::size_t size, const T* list,
- std::size_t count)
-{
- sp_destroyer<E, A, T> hold(allocator, ptr);
- for (std::size_t& i = hold.size(); i < size; ++i) {
- std::allocator_traits<A>::construct(allocator, ptr + i,
- list[i % count]);
- }
- hold.size() = 0;
-}
-#endif
-
-template<class A, class T>
-inline typename
- boost::enable_if_<boost::has_trivial_constructor<T>::value>::type
-sp_array_default(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
-
-template<class A, class T>
-inline typename
- boost::enable_if_<!boost::has_trivial_constructor<T>::value>::type
-sp_array_default(A& none, T* ptr, std::size_t size)
-{
- sp_destroyer<false, A, T> hold(none, ptr);
- for (std::size_t& i = hold.size(); i < size; ++i) {
- ::new(static_cast<void*>(ptr + i)) T;
- }
- hold.size() = 0;
-}
-
template<class A>
class sp_array_state {
public:
@@ -262,29 +120,6 @@ private:
A allocator_;
};
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-template<class A>
-struct sp_use_construct {
- enum {
- value = true
- };
-};
-
-template<class T>
-struct sp_use_construct<std::allocator<T> > {
- enum {
- value = false
- };
-};
-#else
-template<class>
-struct sp_use_construct {
- enum {
- value = false
- };
-};
-#endif
-
template<class T, class U>
struct sp_array_alignment {
enum {
@@ -300,39 +135,32 @@ struct sp_array_offset {
};
};
-template<class T, class U>
-struct sp_array_storage {
- enum {
- value = sp_array_alignment<T, U>::value
- };
- typedef typename boost::type_with_alignment<value>::type type;
-};
-
-template<class T, class U>
+template<class U, class T>
inline U*
-sp_array_start(void* base) BOOST_SP_NOEXCEPT
+sp_array_start(T* base) BOOST_SP_NOEXCEPT
{
enum {
size = sp_array_offset<T, U>::value
};
- return reinterpret_cast<U*>(static_cast<char*>(base) + size);
+ return reinterpret_cast<U*>(reinterpret_cast<char*>(base) + size);
}
template<class A, class T>
class sp_array_creator {
- typedef typename A::value_type scalar;
+ typedef typename A::value_type element;
enum {
- offset = sp_array_offset<T, scalar>::value
+ offset = sp_array_offset<T, element>::value
};
- typedef typename sp_array_storage<T, scalar>::type type;
+ typedef typename boost::type_with_alignment<sp_array_alignment<T,
+ element>::value>::type type;
public:
template<class U>
sp_array_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
: other_(other),
- size_(sp_objects<type>(offset + sizeof(scalar) * size)) { }
+ size_(sp_objects<type>(offset + sizeof(element) * size)) { }
T* create() {
return reinterpret_cast<T*>(other_.allocate(size_));
@@ -347,9 +175,7 @@ private:
std::size_t size_;
};
-struct sp_default { };
-
-template<class T, bool E = sp_use_construct<T>::value>
+template<class T>
class BOOST_SYMBOL_VISIBLE sp_array_base
: public sp_counted_base {
typedef typename T::type allocator;
@@ -358,23 +184,22 @@ public:
typedef typename allocator::value_type type;
template<class A>
- sp_array_base(const A& other, std::size_t size, type* start)
+ sp_array_base(const A& other, type* start, std::size_t size)
: state_(other, size) {
- sp_array_construct<E>(state_.allocator(), start, state_.size());
+ boost::alloc_construct_n(state_.allocator(),
+ boost::first_scalar(start),
+ state_.size() * sp_array_count<type>::value);
}
- template<class A>
- sp_array_base(const A& other, std::size_t size, const type* list,
- std::size_t count, type* start)
- : state_(other, size) {
- sp_array_construct<E>(state_.allocator(), start, state_.size(), list,
- count);
- }
-
- template<class A>
- sp_array_base(sp_default, const A& other, std::size_t size, type* start)
+ template<class A, class U>
+ sp_array_base(const A& other, type* start, std::size_t size, const U& list)
: state_(other, size) {
- sp_array_default(state_.allocator(), start, state_.size());
+ enum {
+ count = sp_array_count<type>::value
+ };
+ boost::alloc_construct_n(state_.allocator(),
+ boost::first_scalar(start), state_.size() * count,
+ boost::first_scalar(&list), count);
}
T& state() BOOST_SP_NOEXCEPT {
@@ -382,8 +207,9 @@ public:
}
virtual void dispose() BOOST_SP_NOEXCEPT {
- sp_array_destroy<E>(state_.allocator(),
- sp_array_start<sp_array_base, type>(this), state_.size());
+ boost::alloc_destroy_n(state_.allocator(),
+ boost::first_scalar(sp_array_start<type>(this)),
+ state_.size() * sp_array_count<type>::value);
}
virtual void destroy() BOOST_SP_NOEXCEPT {
@@ -393,11 +219,11 @@ public:
other.destroy(this);
}
- virtual void* get_deleter(const sp_typeinfo&) BOOST_SP_NOEXCEPT {
+ virtual void* get_deleter(const sp_typeinfo_&) BOOST_SP_NOEXCEPT {
return 0;
}
- virtual void* get_local_deleter(const sp_typeinfo&) BOOST_SP_NOEXCEPT {
+ virtual void* get_local_deleter(const sp_typeinfo_&) BOOST_SP_NOEXCEPT {
return 0;
}
@@ -423,11 +249,11 @@ public:
}
}
- T* get() const {
+ T* get() const BOOST_SP_NOEXCEPT {
return result_;
}
- void release() {
+ void release() BOOST_SP_NOEXCEPT {
result_ = 0;
}
@@ -445,40 +271,37 @@ template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, std::size_t count)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef typename detail::sp_array_element<T>::type element;
+ typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::sp_array_state<other> state;
typedef detail::sp_array_base<state> base;
- std::size_t size = count * detail::sp_array_count<type, scalar>::value;
- detail::sp_array_result<other, base> result(allocator, size);
- detail::sp_counted_base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(allocator, size, start);
+ detail::sp_array_result<other, base> result(allocator, count);
+ base* node = result.get();
+ element* start = detail::sp_array_start<element>(node);
+ ::new(static_cast<void*>(node)) base(allocator, start, count);
result.release();
- return shared_ptr<T>(detail::sp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), detail::shared_count(node));
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
+ detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
- size = detail::sp_array_count<T, scalar>::value
+ count = extent<T>::value
};
- typedef detail::sp_size_array_state<other, size> state;
+ typedef typename detail::sp_array_element<T>::type element;
+ typedef typename detail::sp_bind_allocator<A, element>::type other;
+ typedef detail::sp_size_array_state<other, extent<T>::value> state;
typedef detail::sp_array_base<state> base;
- detail::sp_array_result<other, base> result(allocator, size);
- detail::sp_counted_base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(allocator, size, start);
+ detail::sp_array_result<other, base> result(allocator, count);
+ base* node = result.get();
+ element* start = detail::sp_array_start<element>(node);
+ ::new(static_cast<void*>(node)) base(allocator, start, count);
result.release();
- return shared_ptr<T>(detail::sp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), detail::shared_count(node));
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
+ detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
}
template<class T, class A>
@@ -486,23 +309,17 @@ inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, std::size_t count,
const typename remove_extent<T>::type& value)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef typename detail::sp_array_element<T>::type element;
+ typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::sp_array_state<other> state;
typedef detail::sp_array_base<state> base;
- enum {
- total = detail::sp_array_count<type, scalar>::value
- };
- std::size_t size = count * total;
- detail::sp_array_result<other, base> result(allocator, size);
- detail::sp_counted_base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(allocator, size,
- reinterpret_cast<const scalar*>(&value), total, start);
+ detail::sp_array_result<other, base> result(allocator, count);
+ base* node = result.get();
+ element* start = detail::sp_array_start<element>(node);
+ ::new(static_cast<void*>(node)) base(allocator, start, count, value);
result.release();
- return shared_ptr<T>(detail::sp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), detail::shared_count(node));
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
+ detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
}
template<class T, class A>
@@ -510,65 +327,34 @@ inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator,
const typename remove_extent<T>::type& value)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
- size = detail::sp_array_count<T, scalar>::value
+ count = extent<T>::value
};
- typedef detail::sp_size_array_state<other, size> state;
+ typedef typename detail::sp_array_element<T>::type element;
+ typedef typename detail::sp_bind_allocator<A, element>::type other;
+ typedef detail::sp_size_array_state<other, extent<T>::value> state;
typedef detail::sp_array_base<state> base;
- detail::sp_array_result<other, base> result(allocator, size);
- detail::sp_counted_base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(allocator, size,
- reinterpret_cast<const scalar*>(&value),
- detail::sp_array_count<type, scalar>::value, start);
+ detail::sp_array_result<other, base> result(allocator, count);
+ base* node = result.get();
+ element* start = detail::sp_array_start<element>(node);
+ ::new(static_cast<void*>(node)) base(allocator, start, count, value);
result.release();
- return shared_ptr<T>(detail::sp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), detail::shared_count(node));
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
+ detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
}
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared_noinit(const A& allocator, std::size_t count)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
- typedef detail::sp_array_state<other> state;
- typedef detail::sp_array_base<state, false> base;
- std::size_t size = count * detail::sp_array_count<type, scalar>::value;
- detail::sp_array_result<other, base> result(allocator, size);
- detail::sp_counted_base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
- size, start);
- result.release();
- return shared_ptr<T>(detail::sp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), detail::shared_count(node));
+ return boost::allocate_shared<T>(boost::noinit_adapt(allocator), count);
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared_noinit(const A& allocator)
{
- typedef typename remove_extent<T>::type type;
- typedef typename detail::sp_array_scalar<T>::type scalar;
- typedef typename detail::sp_bind_allocator<A, scalar>::type other;
- enum {
- size = detail::sp_array_count<T, scalar>::value
- };
- typedef detail::sp_size_array_state<other, size> state;
- typedef detail::sp_array_base<state, false> base;
- detail::sp_array_result<other, base> result(allocator, size);
- detail::sp_counted_base* node = result.get();
- scalar* start = detail::sp_array_start<base, scalar>(node);
- ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
- size, start);
- result.release();
- return shared_ptr<T>(detail::sp_internal_constructor_tag(),
- reinterpret_cast<type*>(start), detail::shared_count(node));
+ return boost::allocate_shared<T>(boost::noinit_adapt(allocator));
}
} /* boost */
diff --git a/boost/smart_ptr/atomic_shared_ptr.hpp b/boost/smart_ptr/atomic_shared_ptr.hpp
index 7c485070f8..b863100e53 100644
--- a/boost/smart_ptr/atomic_shared_ptr.hpp
+++ b/boost/smart_ptr/atomic_shared_ptr.hpp
@@ -63,6 +63,11 @@ public:
{
}
+ atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
+ : p_( std::move( p ) ), l_ BOOST_DETAIL_SPINLOCK_INIT
+ {
+ }
+
#else
atomic_shared_ptr() BOOST_SP_NOEXCEPT
@@ -71,8 +76,6 @@ public:
std::memcpy( &l_, &init, sizeof( init ) );
}
-#endif
-
atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
: p_( std::move( p ) )
@@ -84,6 +87,8 @@ public:
std::memcpy( &l_, &init, sizeof( init ) );
}
+#endif
+
atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{
boost::detail::spinlock::scoped_lock lock( l_ );
diff --git a/boost/smart_ptr/detail/atomic_count_std_atomic.hpp b/boost/smart_ptr/detail/atomic_count_std_atomic.hpp
index 55b9998e52..3d5fb78fcb 100644
--- a/boost/smart_ptr/detail/atomic_count_std_atomic.hpp
+++ b/boost/smart_ptr/detail/atomic_count_std_atomic.hpp
@@ -26,7 +26,7 @@ class atomic_count
{
public:
- explicit atomic_count( long v ): value_( v )
+ explicit atomic_count( long v ): value_( static_cast< std::int_least32_t >( v ) )
{
}
diff --git a/boost/smart_ptr/detail/shared_count.hpp b/boost/smart_ptr/detail/shared_count.hpp
index 1ce68e6b57..d56718fe7e 100644
--- a/boost/smart_ptr/detail/shared_count.hpp
+++ b/boost/smart_ptr/detail/shared_count.hpp
@@ -499,12 +499,12 @@ public:
return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
}
- void * get_deleter( sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
+ void * get_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
{
return pi_? pi_->get_deleter( ti ): 0;
}
- void * get_local_deleter( sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
+ void * get_local_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
{
return pi_? pi_->get_local_deleter( ti ): 0;
}
diff --git a/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp b/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
index aa7ea9a20a..07c07e236b 100644
--- a/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
@@ -15,7 +15,7 @@
// Lock-free algorithm by Alexander Terekhov
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <machine/sys/inline.h>
@@ -104,8 +104,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_aix.hpp b/boost/smart_ptr/detail/sp_counted_base_aix.hpp
index cbb642687e..072c667e29 100644
--- a/boost/smart_ptr/detail/sp_counted_base_aix.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_aix.hpp
@@ -20,7 +20,7 @@
// formulation
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <builtins.h>
#include <sys/atomic_op.h>
@@ -96,8 +96,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_clang.hpp b/boost/smart_ptr/detail/sp_counted_base_clang.hpp
index 90b6f224ca..89bcfb80a7 100644
--- a/boost/smart_ptr/detail/sp_counted_base_clang.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_clang.hpp
@@ -15,7 +15,7 @@
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -99,8 +99,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy() BOOST_SP_NOEXCEPT
diff --git a/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp b/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
index c43297e0e4..8e5a414dab 100644
--- a/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
@@ -24,7 +24,7 @@
// formulation
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
@@ -124,8 +124,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp b/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
index ce34b4cbc4..1ab21a5eaf 100644
--- a/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
@@ -25,7 +25,7 @@
// formulation
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
@@ -112,8 +112,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
index 32642df778..73d4533800 100644
--- a/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
@@ -16,7 +16,7 @@
// Lock-free algorithm by Alexander Terekhov
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
@@ -111,8 +111,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
index c4ce0537c9..f109f6579f 100644
--- a/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
@@ -20,7 +20,7 @@
// Lock-free algorithm by Alexander Terekhov
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
@@ -141,8 +141,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
index 5cf5b3fa66..5dce1cf6ac 100644
--- a/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
@@ -24,7 +24,7 @@
// formulation
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
@@ -135,8 +135,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
index 2f27b96e1e..a3d7295865 100644
--- a/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
@@ -19,7 +19,7 @@
//
// Thanks to Michael van der Westhuizen
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <inttypes.h> // int32_t
@@ -120,8 +120,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
index ec44c7066f..ebbea50264 100644
--- a/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
@@ -24,7 +24,7 @@
// formulation
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
@@ -127,8 +127,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_nt.hpp b/boost/smart_ptr/detail/sp_counted_base_nt.hpp
index 8d7b8e9cc8..08300505bb 100644
--- a/boost/smart_ptr/detail/sp_counted_base_nt.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_nt.hpp
@@ -18,7 +18,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -61,8 +61,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy() BOOST_SP_NOEXCEPT
diff --git a/boost/smart_ptr/detail/sp_counted_base_pt.hpp b/boost/smart_ptr/detail/sp_counted_base_pt.hpp
index 1aa6756122..ec850fe6bd 100644
--- a/boost/smart_ptr/detail/sp_counted_base_pt.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_pt.hpp
@@ -18,7 +18,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -72,8 +72,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp b/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp
index 1b9979bfb5..f38eee65f5 100644
--- a/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp
@@ -19,7 +19,7 @@
//
// Thanks to Michael van der Westhuizen
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <inttypes.h> // uint32_t
@@ -115,8 +115,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_solaris.hpp b/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
index c0d69dcdcb..29f6b8a3c2 100644
--- a/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
@@ -20,7 +20,7 @@
// formulation
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <atomic.h>
@@ -62,8 +62,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_spin.hpp b/boost/smart_ptr/detail/sp_counted_base_spin.hpp
index b9966260cb..56911bdb09 100644
--- a/boost/smart_ptr/detail/sp_counted_base_spin.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_spin.hpp
@@ -18,7 +18,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/spinlock_pool.hpp>
#include <boost/config.hpp>
@@ -84,8 +84,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp b/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp
index 2246dda4b6..338eeea718 100644
--- a/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp
@@ -15,7 +15,7 @@
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <atomic>
@@ -91,8 +91,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy() BOOST_SP_NOEXCEPT
diff --git a/boost/smart_ptr/detail/sp_counted_base_sync.hpp b/boost/smart_ptr/detail/sp_counted_base_sync.hpp
index 17128cc97e..8446560e0a 100644
--- a/boost/smart_ptr/detail/sp_counted_base_sync.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_sync.hpp
@@ -15,7 +15,7 @@
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <limits.h>
@@ -109,8 +109,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp b/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp
index 088ed63972..2467e95a17 100644
--- a/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp
@@ -21,7 +21,7 @@
// formulation
//
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
extern "builtin" void __lwsync(void);
@@ -104,8 +104,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_base_w32.hpp b/boost/smart_ptr/detail/sp_counted_base_w32.hpp
index 46bd4d15a9..9ab71eff87 100644
--- a/boost/smart_ptr/detail/sp_counted_base_w32.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base_w32.hpp
@@ -25,8 +25,8 @@
//
#include <boost/smart_ptr/detail/sp_interlocked.hpp>
+#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/detail/workaround.hpp>
-#include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
namespace boost
@@ -67,8 +67,8 @@ public:
delete this;
}
- virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
- virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
diff --git a/boost/smart_ptr/detail/sp_counted_impl.hpp b/boost/smart_ptr/detail/sp_counted_impl.hpp
index 29718b6b8c..96c9da3830 100644
--- a/boost/smart_ptr/detail/sp_counted_impl.hpp
+++ b/boost/smart_ptr/detail/sp_counted_impl.hpp
@@ -93,12 +93,12 @@ public:
boost::checked_delete( px_ );
}
- virtual void * get_deleter( sp_typeinfo const & ) BOOST_SP_NOEXCEPT
+ virtual void * get_deleter( sp_typeinfo_ const & ) BOOST_SP_NOEXCEPT
{
return 0;
}
- virtual void * get_local_deleter( sp_typeinfo const & ) BOOST_SP_NOEXCEPT
+ virtual void * get_local_deleter( sp_typeinfo_ const & ) BOOST_SP_NOEXCEPT
{
return 0;
}
@@ -173,14 +173,14 @@ public:
del( ptr );
}
- virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT
{
- return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
+ return ti == BOOST_SP_TYPEID_(D)? &reinterpret_cast<char&>( del ): 0;
}
- virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT
{
- return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0;
+ return ti == BOOST_SP_TYPEID_(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0;
}
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT
@@ -266,14 +266,14 @@ public:
a2.deallocate( this, 1 );
}
- virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
+ virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT
{
- return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;
+ return ti == BOOST_SP_TYPEID_( D )? &reinterpret_cast<char&>( d_ ): 0;
}
- virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
+ virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT
{
- return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0;
+ return ti == BOOST_SP_TYPEID_( D )? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0;
}
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT
diff --git a/boost/smart_ptr/detail/sp_typeinfo_.hpp b/boost/smart_ptr/detail/sp_typeinfo_.hpp
new file mode 100644
index 0000000000..287bf72818
--- /dev/null
+++ b/boost/smart_ptr/detail/sp_typeinfo_.hpp
@@ -0,0 +1,58 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_TYPEINFO_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_TYPEINFO_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// smart_ptr/detail/sp_typeinfo_.hpp
+//
+// Copyright 2007, 2019 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_NO_TYPEID ) || defined( BOOST_NO_STD_TYPEINFO )
+
+#include <boost/core/typeinfo.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+typedef boost::core::typeinfo sp_typeinfo_;
+
+} // namespace detail
+
+} // namespace boost
+
+#define BOOST_SP_TYPEID_(T) BOOST_CORE_TYPEID(T)
+
+#else // defined( BOOST_NO_TYPEID ) || defined( BOOST_NO_STD_TYPEINFO )
+
+#include <typeinfo>
+
+namespace boost
+{
+
+namespace detail
+{
+
+typedef std::type_info sp_typeinfo_;
+
+} // namespace detail
+
+} // namespace boost
+
+#define BOOST_SP_TYPEID_(T) typeid(T)
+
+#endif // defined( BOOST_NO_TYPEID ) || defined( BOOST_NO_STD_TYPEINFO )
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_TYPEINFO_HPP_INCLUDED
diff --git a/boost/smart_ptr/enable_shared_from.hpp b/boost/smart_ptr/enable_shared_from.hpp
new file mode 100644
index 0000000000..db347e6f47
--- /dev/null
+++ b/boost/smart_ptr/enable_shared_from.hpp
@@ -0,0 +1,37 @@
+#ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_HPP_INCLUDED
+#define BOOST_SMART_PTR_ENABLE_SHARED_FROM_HPP_INCLUDED
+
+// enable_shared_from.hpp
+//
+// Copyright 2019 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/enable_shared_from_this.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
+
+namespace boost
+{
+
+class enable_shared_from: public enable_shared_from_this<enable_shared_from>
+{
+};
+
+
+template<class T> shared_ptr<T> shared_from( T * p )
+{
+ return shared_ptr<T>( p->enable_shared_from::shared_from_this(), p );
+}
+
+template<class T> weak_ptr<T> weak_from( T * p ) BOOST_SP_NOEXCEPT
+{
+ return weak_ptr<T>( p->enable_shared_from::weak_from_this(), p );
+}
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_HPP_INCLUDED
diff --git a/boost/smart_ptr/enable_shared_from_raw.hpp b/boost/smart_ptr/enable_shared_from_raw.hpp
index 5cd3574e7c..d1c47e7344 100644
--- a/boost/smart_ptr/enable_shared_from_raw.hpp
+++ b/boost/smart_ptr/enable_shared_from_raw.hpp
@@ -144,8 +144,7 @@ template<typename T>
boost::weak_ptr<T> weak_from_raw(T *p)
{
BOOST_ASSERT(p != 0);
- boost::weak_ptr<T> result;
- result._internal_aliasing_assign(p->enable_shared_from_raw::weak_from_this(), p);
+ boost::weak_ptr<T> result(p->enable_shared_from_raw::weak_from_this(), p);
return result;
}
diff --git a/boost/smart_ptr/intrusive_ptr.hpp b/boost/smart_ptr/intrusive_ptr.hpp
index 0ab075d367..eddbb42e1c 100644
--- a/boost/smart_ptr/intrusive_ptr.hpp
+++ b/boost/smart_ptr/intrusive_ptr.hpp
@@ -297,6 +297,8 @@ template<class T> T * get_pointer(intrusive_ptr<T> const & p) BOOST_SP_NOEXCEPT
return p.get();
}
+// pointer casts
+
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
{
return static_cast<T *>(p.get());
@@ -312,6 +314,31 @@ template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U
return dynamic_cast<T *>(p.get());
}
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+template<class T, class U> intrusive_ptr<T> static_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
+{
+ return intrusive_ptr<T>( static_cast<T*>( p.detach() ), false );
+}
+
+template<class T, class U> intrusive_ptr<T> const_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
+{
+ return intrusive_ptr<T>( const_cast<T*>( p.detach() ), false );
+}
+
+template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
+{
+ T * p2 = dynamic_cast<T*>( p.get() );
+
+ intrusive_ptr<T> r( p2, false );
+
+ if( p2 ) p.detach();
+
+ return r;
+}
+
+#endif // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
// operator<<
#if !defined(BOOST_NO_IOSTREAM)
diff --git a/boost/smart_ptr/make_local_shared_array.hpp b/boost/smart_ptr/make_local_shared_array.hpp
index 1d501028c2..ba88c737f3 100644
--- a/boost/smart_ptr/make_local_shared_array.hpp
+++ b/boost/smart_ptr/make_local_shared_array.hpp
@@ -9,6 +9,7 @@ Distributed under the Boost Software License, Version 1.0.
#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP
+#include <boost/core/default_allocator.hpp>
#include <boost/smart_ptr/allocate_local_shared_array.hpp>
namespace boost {
@@ -18,8 +19,8 @@ inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared()
{
- return boost::allocate_local_shared<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>());
+ return boost::allocate_local_shared<T>(boost::default_allocator<typename
+ detail::sp_array_element<T>::type>());
}
template<class T>
@@ -27,8 +28,8 @@ inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared(const typename remove_extent<T>::type& value)
{
- return boost::allocate_local_shared<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>(), value);
+ return boost::allocate_local_shared<T>(boost::default_allocator<typename
+ detail::sp_array_element<T>::type>(), value);
}
template<class T>
@@ -36,8 +37,8 @@ inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared(std::size_t size)
{
- return boost::allocate_local_shared<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>(), size);
+ return boost::allocate_local_shared<T>(boost::default_allocator<typename
+ detail::sp_array_element<T>::type>(), size);
}
template<class T>
@@ -46,8 +47,8 @@ inline typename enable_if_<is_unbounded_array<T>::value,
make_local_shared(std::size_t size,
const typename remove_extent<T>::type& value)
{
- return boost::allocate_local_shared<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>(), size, value);
+ return boost::allocate_local_shared<T>(boost::default_allocator<typename
+ detail::sp_array_element<T>::type>(), size, value);
}
template<class T>
@@ -55,8 +56,8 @@ inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared_noinit()
{
- return boost::allocate_local_shared_noinit<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>());
+ return boost::allocate_local_shared_noinit<T>(boost::
+ default_allocator<typename detail::sp_array_element<T>::type>());
}
template<class T>
@@ -64,8 +65,8 @@ inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared_noinit(std::size_t size)
{
- return boost::allocate_local_shared_noinit<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>(), size);
+ return boost::allocate_local_shared_noinit<T>(boost::
+ default_allocator<typename detail::sp_array_element<T>::type>(), size);
}
} /* boost */
diff --git a/boost/smart_ptr/make_shared_array.hpp b/boost/smart_ptr/make_shared_array.hpp
index 1b40c4d6a8..785eb875fc 100644
--- a/boost/smart_ptr/make_shared_array.hpp
+++ b/boost/smart_ptr/make_shared_array.hpp
@@ -8,6 +8,7 @@ Distributed under the Boost Software License, Version 1.0.
#ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
+#include <boost/core/default_allocator.hpp>
#include <boost/smart_ptr/allocate_shared_array.hpp>
namespace boost {
@@ -16,48 +17,48 @@ template<class T>
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared()
{
- return boost::allocate_shared<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>());
+ return boost::allocate_shared<T>(boost::default_allocator<typename
+ detail::sp_array_element<T>::type>());
}
template<class T>
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared(const typename remove_extent<T>::type& value)
{
- return boost::allocate_shared<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>(), value);
+ return boost::allocate_shared<T>(boost::default_allocator<typename
+ detail::sp_array_element<T>::type>(), value);
}
template<class T>
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared(std::size_t size)
{
- return boost::allocate_shared<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>(), size);
+ return boost::allocate_shared<T>(boost::default_allocator<typename
+ detail::sp_array_element<T>::type>(), size);
}
template<class T>
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared(std::size_t size, const typename remove_extent<T>::type& value)
{
- return boost::allocate_shared<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>(), size, value);
+ return boost::allocate_shared<T>(boost::default_allocator<typename
+ detail::sp_array_element<T>::type>(), size, value);
}
template<class T>
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared_noinit()
{
- return boost::allocate_shared_noinit<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>());
+ return boost::allocate_shared_noinit<T>(boost::default_allocator<typename
+ detail::sp_array_element<T>::type>());
}
template<class T>
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared_noinit(std::size_t size)
{
- return boost::allocate_shared_noinit<T>(std::allocator<typename
- detail::sp_array_scalar<T>::type>(), size);
+ return boost::allocate_shared_noinit<T>(boost::default_allocator<typename
+ detail::sp_array_element<T>::type>(), size);
}
} /* boost */
diff --git a/boost/smart_ptr/shared_array.hpp b/boost/smart_ptr/shared_array.hpp
index 3ffa7426c3..a785f8ee1e 100644
--- a/boost/smart_ptr/shared_array.hpp
+++ b/boost/smart_ptr/shared_array.hpp
@@ -225,7 +225,7 @@ public:
pn.swap(other.pn);
}
- void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
+ void * _internal_get_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
{
return pn.get_deleter( ti );
}
@@ -285,7 +285,7 @@ template<class T> void swap(shared_array<T> & a, shared_array<T> & b) BOOST_SP_N
template< class D, class T > D * get_deleter( shared_array<T> const & p ) BOOST_SP_NOEXCEPT
{
- return static_cast< D * >( p._internal_get_deleter( BOOST_SP_TYPEID(D) ) );
+ return static_cast< D * >( p._internal_get_deleter( BOOST_SP_TYPEID_(D) ) );
}
} // namespace boost
diff --git a/boost/smart_ptr/shared_ptr.hpp b/boost/smart_ptr/shared_ptr.hpp
index baafc499f7..5ac02beb2d 100644
--- a/boost/smart_ptr/shared_ptr.hpp
+++ b/boost/smart_ptr/shared_ptr.hpp
@@ -777,12 +777,12 @@ public:
return pn < rhs.pn;
}
- void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
+ void * _internal_get_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
{
return pn.get_deleter( ti );
}
- void * _internal_get_local_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
+ void * _internal_get_local_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
{
return pn.get_local_deleter( ti );
}
@@ -1008,7 +1008,7 @@ namespace detail
template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
- return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID(D)) );
+ return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID_(D)) );
}
template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT;
@@ -1165,12 +1165,12 @@ namespace detail
template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
- return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID(local_sp_deleter<D>) ) );
+ return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>) ) );
}
template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
- return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID(local_sp_deleter<D>) ) );
+ return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>) ) );
}
} // namespace detail
diff --git a/boost/smart_ptr/weak_ptr.hpp b/boost/smart_ptr/weak_ptr.hpp
index 54d9ef3781..5230f35e68 100644
--- a/boost/smart_ptr/weak_ptr.hpp
+++ b/boost/smart_ptr/weak_ptr.hpp
@@ -137,6 +137,23 @@ public:
boost::detail::sp_assert_convertible< Y, T >();
}
+ // aliasing
+ template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( r.pn )
+ {
+ }
+
+ template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( r.pn )
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( std::move( r.pn ) )
+ {
+ }
+
+#endif
+
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
template<class Y>
@@ -194,6 +211,11 @@ public:
return pn.empty();
}
+ bool empty() const BOOST_SP_NOEXCEPT // extension, not in std::weak_ptr
+ {
+ return pn.empty();
+ }
+
void reset() BOOST_SP_NOEXCEPT
{
this_type().swap(*this);
@@ -205,13 +227,6 @@ public:
pn.swap(other.pn);
}
- template<typename Y>
- void _internal_aliasing_assign(weak_ptr<Y> const & r, element_type * px2) BOOST_SP_NOEXCEPT
- {
- px = px2;
- pn = r.pn;
- }
-
template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
{
return pn < rhs.pn;
diff --git a/boost/spirit/home/karma/auto/auto.hpp b/boost/spirit/home/karma/auto/auto.hpp
index 5d1a0a17bd..6e836364b9 100644
--- a/boost/spirit/home/karma/auto/auto.hpp
+++ b/boost/spirit/home/karma/auto/auto.hpp
@@ -146,9 +146,8 @@ namespace boost { namespace spirit { namespace karma
T t_;
generator_impl_type generator_;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- lit_auto_generator& operator= (lit_auto_generator const&);
+ BOOST_DELETED_FUNCTION(lit_auto_generator& operator= (lit_auto_generator const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/karma/auxiliary/lazy.hpp b/boost/spirit/home/karma/auxiliary/lazy.hpp
index 49cdf12d81..bc9c1ed47c 100644
--- a/boost/spirit/home/karma/auxiliary/lazy.hpp
+++ b/boost/spirit/home/karma/auxiliary/lazy.hpp
@@ -139,9 +139,8 @@ namespace boost { namespace spirit { namespace karma
Function func;
Modifiers modifiers;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- lazy_generator& operator= (lazy_generator const&);
+ BOOST_DELETED_FUNCTION(lazy_generator& operator= (lazy_generator const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/karma/detail/alternative_function.hpp b/boost/spirit/home/karma/detail/alternative_function.hpp
index 8e369b42e3..57a3f6b1ce 100644
--- a/boost/spirit/home/karma/detail/alternative_function.hpp
+++ b/boost/spirit/home/karma/detail/alternative_function.hpp
@@ -191,9 +191,8 @@ namespace boost { namespace spirit { namespace karma { namespace detail
Delimiter const& delim;
Attribute const& attr;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- alternative_generate_function& operator= (alternative_generate_function const&);
+ BOOST_DELETED_FUNCTION(alternative_generate_function& operator= (alternative_generate_function const&))
};
// specialization for strict alternatives
@@ -241,9 +240,8 @@ namespace boost { namespace spirit { namespace karma { namespace detail
Attribute const& attr;
bool failed;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- alternative_generate_function& operator= (alternative_generate_function const&);
+ BOOST_DELETED_FUNCTION(alternative_generate_function& operator= (alternative_generate_function const&))
};
}}}}
diff --git a/boost/spirit/home/karma/detail/fail_function.hpp b/boost/spirit/home/karma/detail/fail_function.hpp
index 5310d54329..7043f43b88 100644
--- a/boost/spirit/home/karma/detail/fail_function.hpp
+++ b/boost/spirit/home/karma/detail/fail_function.hpp
@@ -50,9 +50,8 @@ namespace boost { namespace spirit { namespace karma { namespace detail
Context& ctx;
Delimiter const& delim;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- fail_function& operator= (fail_function const&);
+ BOOST_DELETED_FUNCTION(fail_function& operator= (fail_function const&))
};
}}}}
diff --git a/boost/spirit/home/karma/detail/pass_container.hpp b/boost/spirit/home/karma/detail/pass_container.hpp
index 41c253d4b0..5c6703bad5 100644
--- a/boost/spirit/home/karma/detail/pass_container.hpp
+++ b/boost/spirit/home/karma/detail/pass_container.hpp
@@ -383,9 +383,8 @@ namespace boost { namespace spirit { namespace karma { namespace detail
F f;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- pass_container& operator= (pass_container const&);
+ BOOST_DELETED_FUNCTION(pass_container& operator= (pass_container const&))
};
}}}}
diff --git a/boost/spirit/home/karma/detail/unused_delimiter.hpp b/boost/spirit/home/karma/detail/unused_delimiter.hpp
index 793c8f0f67..cec13cac17 100644
--- a/boost/spirit/home/karma/detail/unused_delimiter.hpp
+++ b/boost/spirit/home/karma/detail/unused_delimiter.hpp
@@ -21,9 +21,8 @@ namespace boost { namespace spirit { namespace karma { namespace detail
: delimiter(delim) {}
Delimiter const& delimiter;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- unused_delimiter& operator= (unused_delimiter const&);
+ BOOST_DELETED_FUNCTION(unused_delimiter& operator= (unused_delimiter const&))
};
// If a surrounding verbatim[] directive was specified, the current
diff --git a/boost/spirit/home/karma/directive/columns.hpp b/boost/spirit/home/karma/directive/columns.hpp
index 78010db14a..85892849b7 100644
--- a/boost/spirit/home/karma/directive/columns.hpp
+++ b/boost/spirit/home/karma/directive/columns.hpp
@@ -109,9 +109,8 @@ namespace boost { namespace spirit { namespace karma
unsigned int const numcolumns;
mutable unsigned int count;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- columns_delimiter& operator= (columns_delimiter const&);
+ BOOST_DELETED_FUNCTION(columns_delimiter& operator= (columns_delimiter const&))
};
}
diff --git a/boost/spirit/home/karma/directive/repeat.hpp b/boost/spirit/home/karma/directive/repeat.hpp
index f6b4378e78..3262334d94 100644
--- a/boost/spirit/home/karma/directive/repeat.hpp
+++ b/boost/spirit/home/karma/directive/repeat.hpp
@@ -91,9 +91,8 @@ namespace boost { namespace spirit { namespace karma
T const exact;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- exact_iterator& operator= (exact_iterator const&);
+ BOOST_DELETED_FUNCTION(exact_iterator& operator= (exact_iterator const&))
};
// handles repeat(min, max)[p]
@@ -112,9 +111,8 @@ namespace boost { namespace spirit { namespace karma
T const min;
T const max;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- finite_iterator& operator= (finite_iterator const&);
+ BOOST_DELETED_FUNCTION(finite_iterator& operator= (finite_iterator const&))
};
// handles repeat(min, inf)[p]
@@ -131,9 +129,8 @@ namespace boost { namespace spirit { namespace karma
T const min;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- infinite_iterator& operator= (infinite_iterator const&);
+ BOOST_DELETED_FUNCTION(infinite_iterator& operator= (infinite_iterator const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/karma/stream/detail/format_manip.hpp b/boost/spirit/home/karma/stream/detail/format_manip.hpp
index 0c771fc554..e8ac36ecb3 100644
--- a/boost/spirit/home/karma/stream/detail/format_manip.hpp
+++ b/boost/spirit/home/karma/stream/detail/format_manip.hpp
@@ -43,9 +43,8 @@ namespace boost { namespace spirit { namespace karma { namespace detail
BOOST_SCOPED_ENUM(delimit_flag) const pre;
Attribute const& attr;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- format_manip& operator= (format_manip const&);
+ BOOST_DELETED_FUNCTION(format_manip& operator= (format_manip const&))
};
template <typename Expr, typename Delimiter, typename Attribute>
@@ -63,9 +62,8 @@ namespace boost { namespace spirit { namespace karma { namespace detail
BOOST_SCOPED_ENUM(delimit_flag) const pre;
Attribute attr;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- format_manip& operator= (format_manip const&);
+ BOOST_DELETED_FUNCTION(format_manip& operator= (format_manip const&))
};
template <typename Expr, typename Delimiter, typename Attribute>
@@ -83,9 +81,8 @@ namespace boost { namespace spirit { namespace karma { namespace detail
BOOST_SCOPED_ENUM(delimit_flag) const pre;
Attribute const& attr;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- format_manip& operator= (format_manip const&);
+ BOOST_DELETED_FUNCTION(format_manip& operator= (format_manip const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/karma/stream/detail/iterator_sink.hpp b/boost/spirit/home/karma/stream/detail/iterator_sink.hpp
index 95a57d42f1..9aa3915332 100644
--- a/boost/spirit/home/karma/stream/detail/iterator_sink.hpp
+++ b/boost/spirit/home/karma/stream/detail/iterator_sink.hpp
@@ -45,9 +45,8 @@ namespace boost { namespace spirit { namespace karma { namespace detail
OutputIterator& sink;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- iterator_sink& operator= (iterator_sink const&);
+ BOOST_DELETED_FUNCTION(iterator_sink& operator= (iterator_sink const&))
};
}}}}
diff --git a/boost/spirit/home/karma/stream/stream.hpp b/boost/spirit/home/karma/stream/stream.hpp
index 1b679a8aab..be6588362f 100644
--- a/boost/spirit/home/karma/stream/stream.hpp
+++ b/boost/spirit/home/karma/stream/stream.hpp
@@ -285,9 +285,8 @@ namespace boost { namespace spirit { namespace karma
T t_;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- lit_stream_generator& operator= (lit_stream_generator const&);
+ BOOST_DELETED_FUNCTION(lit_stream_generator& operator= (lit_stream_generator const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/karma/string/symbols.hpp b/boost/spirit/home/karma/string/symbols.hpp
index 72c82d1115..31eca1b9fe 100644
--- a/boost/spirit/home/karma/string/symbols.hpp
+++ b/boost/spirit/home/karma/string/symbols.hpp
@@ -411,9 +411,8 @@ namespace boost { namespace spirit { namespace karma
symbols& sym;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- adder& operator= (adder const&);
+ BOOST_DELETED_FUNCTION(adder& operator= (adder const&))
};
struct remover
@@ -444,9 +443,8 @@ namespace boost { namespace spirit { namespace karma
symbols& sym;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- remover& operator= (remover const&);
+ BOOST_DELETED_FUNCTION(remover& operator= (remover const&))
};
adder add;
@@ -670,9 +668,8 @@ namespace boost { namespace spirit { namespace karma
symbols& sym;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- adder& operator= (adder const&);
+ BOOST_DELETED_FUNCTION(adder& operator= (adder const&))
};
struct remover
@@ -703,9 +700,8 @@ namespace boost { namespace spirit { namespace karma
symbols& sym;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- remover& operator= (remover const&);
+ BOOST_DELETED_FUNCTION(remover& operator= (remover const&))
};
adder add;
diff --git a/boost/spirit/home/lex/detail/sequence_function.hpp b/boost/spirit/home/lex/detail/sequence_function.hpp
index 0f52da8413..4f41ccbb45 100644
--- a/boost/spirit/home/lex/detail/sequence_function.hpp
+++ b/boost/spirit/home/lex/detail/sequence_function.hpp
@@ -33,9 +33,8 @@ namespace boost { namespace spirit { namespace lex { namespace detail
String const& state;
String const& targetstate;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- sequence_collect_function& operator= (sequence_collect_function const&);
+ BOOST_DELETED_FUNCTION(sequence_collect_function& operator= (sequence_collect_function const&))
};
template <typename LexerDef>
@@ -53,9 +52,8 @@ namespace boost { namespace spirit { namespace lex { namespace detail
LexerDef& def;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- sequence_add_actions_function& operator= (sequence_add_actions_function const&);
+ BOOST_DELETED_FUNCTION(sequence_add_actions_function& operator= (sequence_add_actions_function const&))
};
}}}}
diff --git a/boost/spirit/home/lex/lexer/action.hpp b/boost/spirit/home/lex/lexer/action.hpp
index 8de0c87b71..c0eb07da80 100644
--- a/boost/spirit/home/lex/lexer/action.hpp
+++ b/boost/spirit/home/lex/lexer/action.hpp
@@ -51,9 +51,8 @@ namespace boost { namespace spirit { namespace lex
Subject subject;
Action f;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- action& operator= (action const&);
+ BOOST_DELETED_FUNCTION(action& operator= (action const&))
};
}}}
diff --git a/boost/spirit/home/lex/lexer/lexer.hpp b/boost/spirit/home/lex/lexer/lexer.hpp
index f57e07d4fd..7da9e775df 100644
--- a/boost/spirit/home/lex/lexer/lexer.hpp
+++ b/boost/spirit/home/lex/lexer/lexer.hpp
@@ -181,9 +181,8 @@ namespace boost { namespace spirit { namespace lex
lexer_def_& def;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- adder& operator= (adder const&);
+ BOOST_DELETED_FUNCTION(adder& operator= (adder const&))
};
friend struct adder;
@@ -203,9 +202,8 @@ namespace boost { namespace spirit { namespace lex
lexer_def_& def;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- pattern_adder& operator= (pattern_adder const&);
+ BOOST_DELETED_FUNCTION(pattern_adder& operator= (pattern_adder const&))
};
friend struct pattern_adder;
@@ -280,9 +278,8 @@ namespace boost { namespace spirit { namespace lex
string_type state;
string_type targetstate;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- lexer_def_& operator= (lexer_def_ const&);
+ BOOST_DELETED_FUNCTION(lexer_def_& operator= (lexer_def_ const&))
};
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
diff --git a/boost/spirit/home/lex/lexer/lexertl/functor.hpp b/boost/spirit/home/lex/lexer/lexertl/functor.hpp
index 273e269d6e..9c894b3c06 100644
--- a/boost/spirit/home/lex/lexer/lexertl/functor.hpp
+++ b/boost/spirit/home/lex/lexer/lexertl/functor.hpp
@@ -92,9 +92,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
T& dst_;
T const& src_;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- assign_on_exit& operator= (assign_on_exit const&);
+ BOOST_DELETED_FUNCTION(assign_on_exit& operator= (assign_on_exit const&))
};
public:
diff --git a/boost/spirit/home/lex/lexer/lexertl/functor_data.hpp b/boost/spirit/home/lex/lexer/lexertl/functor_data.hpp
index e348100359..b32f536ba5 100644
--- a/boost/spirit/home/lex/lexer/lexertl/functor_data.hpp
+++ b/boost/spirit/home/lex/lexer/lexertl/functor_data.hpp
@@ -193,9 +193,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
bool bol_; // helper storing whether last character was \n
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- data& operator= (data const&);
+ BOOST_DELETED_FUNCTION(data& operator= (data const&))
};
///////////////////////////////////////////////////////////////////////
@@ -266,9 +265,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
protected:
std::size_t state_;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- data& operator= (data const&);
+ BOOST_DELETED_FUNCTION(data& operator= (data const&))
};
///////////////////////////////////////////////////////////////////////
@@ -300,7 +298,7 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
template <typename IterData>
data (IterData const& data_, Iterator& first, Iterator const& last)
: base_type(data_, first, last)
- , actions_(data_.actions_), hold_()
+ , actions_(data_.actions_), hold_(), end_()
, value_(iterator_range<Iterator>(last, last))
, has_value_(false), has_hold_(false) {}
@@ -402,9 +400,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
mutable bool has_value_; // 'true' if value_ is valid
bool has_hold_; // 'true' if hold_ is valid
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- data& operator= (data const&);
+ BOOST_DELETED_FUNCTION(data& operator= (data const&))
};
///////////////////////////////////////////////////////////////////////
@@ -542,9 +539,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
mutable bool has_value_; // 'true' if value_ is valid
bool has_hold_; // 'true' if hold_ is valid
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- data& operator= (data const&);
+ BOOST_DELETED_FUNCTION(data& operator= (data const&))
};
}
}}}}
diff --git a/boost/spirit/home/lex/lexer/lexertl/lexer.hpp b/boost/spirit/home/lex/lexer/lexertl/lexer.hpp
index ea9fab4fbf..ae22706360 100644
--- a/boost/spirit/home/lex/lexer/lexertl/lexer.hpp
+++ b/boost/spirit/home/lex/lexer/lexertl/lexer.hpp
@@ -188,9 +188,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
boost::lexer::basic_rules<char_type> const& rules_;
semantic_actions_type const& actions_;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- iterator_data_type& operator= (iterator_data_type const&);
+ BOOST_DELETED_FUNCTION(iterator_data_type& operator= (iterator_data_type const&))
};
public:
diff --git a/boost/spirit/home/lex/lexer/lexertl/static_functor_data.hpp b/boost/spirit/home/lex/lexer/lexertl/static_functor_data.hpp
index 109be2a7f8..aa8d60aeff 100644
--- a/boost/spirit/home/lex/lexer/lexertl/static_functor_data.hpp
+++ b/boost/spirit/home/lex/lexer/lexertl/static_functor_data.hpp
@@ -209,9 +209,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
bool bol_; // helper storing whether last character was \n
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- static_data& operator= (static_data const&);
+ BOOST_DELETED_FUNCTION(static_data& operator= (static_data const&))
};
///////////////////////////////////////////////////////////////////////
@@ -284,9 +283,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
std::size_t state_;
std::size_t num_states_;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- static_data& operator= (static_data const&);
+ BOOST_DELETED_FUNCTION(static_data& operator= (static_data const&))
};
///////////////////////////////////////////////////////////////////////
@@ -423,9 +421,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
mutable bool has_value_; // 'true' if value_ is valid
bool has_hold_; // 'true' if hold_ is valid
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- static_data& operator= (static_data const&);
+ BOOST_DELETED_FUNCTION(static_data& operator= (static_data const&))
};
///////////////////////////////////////////////////////////////////////
@@ -563,9 +560,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
mutable bool has_value_; // 'true' if value_ is valid
bool has_hold_; // 'true' if hold_ is valid
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- static_data& operator= (static_data const&);
+ BOOST_DELETED_FUNCTION(static_data& operator= (static_data const&))
};
}
}}}}
diff --git a/boost/spirit/home/lex/lexer/lexertl/static_lexer.hpp b/boost/spirit/home/lex/lexer/lexertl/static_lexer.hpp
index e41526bab7..ac815b15bd 100644
--- a/boost/spirit/home/lex/lexer/lexertl/static_lexer.hpp
+++ b/boost/spirit/home/lex/lexer/lexertl/static_lexer.hpp
@@ -151,9 +151,8 @@ namespace boost { namespace spirit { namespace lex { namespace lexertl
std::size_t num_states_;
bool bol_;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- iterator_data_type& operator= (iterator_data_type const&);
+ BOOST_DELETED_FUNCTION(iterator_data_type& operator= (iterator_data_type const&))
};
typedef LexerTables tables_type;
diff --git a/boost/spirit/home/lex/qi/state_switcher.hpp b/boost/spirit/home/lex/qi/state_switcher.hpp
index a8fd55a352..8be81b150a 100644
--- a/boost/spirit/home/lex/qi/state_switcher.hpp
+++ b/boost/spirit/home/lex/qi/state_switcher.hpp
@@ -154,9 +154,8 @@ namespace boost { namespace spirit { namespace qi
Iterator& it;
std::size_t state;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- reset_state_on_exit& operator= (reset_state_on_exit const&);
+ BOOST_DELETED_FUNCTION(reset_state_on_exit& operator= (reset_state_on_exit const&))
};
}
@@ -214,9 +213,8 @@ namespace boost { namespace spirit { namespace qi
Subject subject;
State state;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- state_switcher_context& operator= (state_switcher_context const&);
+ BOOST_DELETED_FUNCTION(state_switcher_context& operator= (state_switcher_context const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/lex/tokenize_and_parse_attr.hpp b/boost/spirit/home/lex/tokenize_and_parse_attr.hpp
index 98d191d32a..163dfff6a6 100644
--- a/boost/spirit/home/lex/tokenize_and_parse_attr.hpp
+++ b/boost/spirit/home/lex/tokenize_and_parse_attr.hpp
@@ -57,54 +57,6 @@ namespace boost { namespace spirit { namespace lex
return compile<qi::domain>(expr).parse(
iter, lex.end(), unused, unused, attr);
}
-
- ///////////////////////////////////////////////////////////////////////////
- template <typename Iterator, typename Lexer, typename ParserExpr
- , typename Skipper, BOOST_PP_ENUM_PARAMS(N, typename A)>
- inline bool
- tokenize_and_phrase_parse(Iterator& first, Iterator last, Lexer const& lex
- , ParserExpr const& expr, Skipper const& skipper
- , BOOST_SCOPED_ENUM(skip_flag) post_skip
- , BOOST_PP_ENUM_BINARY_PARAMS(N, A, & attr))
- {
- // Report invalid expression error as early as possible.
- // If you got an error_invalid_expression error message here,
- // then either the expression (expr) or skipper is not a valid
- // spirit qi expression.
- BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
- BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Skipper);
-
- typedef
- typename spirit::result_of::compile<qi::domain, Skipper>::type
- skipper_type;
- skipper_type const skipper_ = compile<qi::domain>(skipper);
-
- typedef fusion::vector<
- BOOST_PP_ENUM(N, BOOST_SPIRIT_QI_ATTRIBUTE_REFERENCE, A)
- > vector_type;
-
- vector_type attr (BOOST_PP_ENUM_PARAMS(N, attr));
- typename Lexer::iterator_type iter = lex.begin(first, last);
- if (!compile<qi::domain>(expr).parse(
- iter, lex.end(), unused, skipper_, attr))
- return false;
-
- if (post_skip == skip_flag::postskip)
- qi::skip_over(first, last, skipper_);
- return true;
- }
-
- template <typename Iterator, typename Lexer, typename ParserExpr
- , typename Skipper, BOOST_PP_ENUM_PARAMS(N, typename A)>
- inline bool
- tokenize_and_phrase_parse(Iterator& first, Iterator last, Lexer const& lex
- , ParserExpr const& expr, Skipper const& skipper
- , BOOST_PP_ENUM_BINARY_PARAMS(N, A, & attr))
- {
- return tokenize_and_phrase_parse(first, last, expr, skipper
- , skip_flag::postskip, BOOST_PP_ENUM_PARAMS(N, attr));
- }
-
}}}
#undef BOOST_SPIRIT_QI_ATTRIBUTE_REFERENCE
diff --git a/boost/spirit/home/qi/action/action.hpp b/boost/spirit/home/qi/action/action.hpp
index 286adb267f..d54ad976b2 100644
--- a/boost/spirit/home/qi/action/action.hpp
+++ b/boost/spirit/home/qi/action/action.hpp
@@ -137,9 +137,8 @@ namespace boost { namespace spirit { namespace qi
Subject subject;
Action f;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- action& operator= (action const&);
+ BOOST_DELETED_FUNCTION(action& operator= (action const&))
};
}}}
diff --git a/boost/spirit/home/qi/auxiliary/attr.hpp b/boost/spirit/home/qi/auxiliary/attr.hpp
index fb018e7d73..c1abf07859 100644
--- a/boost/spirit/home/qi/auxiliary/attr.hpp
+++ b/boost/spirit/home/qi/auxiliary/attr.hpp
@@ -73,9 +73,8 @@ namespace boost { namespace spirit { namespace qi
Value value_;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- attr_parser& operator= (attr_parser const&);
+ BOOST_DELETED_FUNCTION(attr_parser& operator= (attr_parser const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/qi/auxiliary/attr_cast.hpp b/boost/spirit/home/qi/auxiliary/attr_cast.hpp
index 746679d371..a0563dec86 100644
--- a/boost/spirit/home/qi/auxiliary/attr_cast.hpp
+++ b/boost/spirit/home/qi/auxiliary/attr_cast.hpp
@@ -114,9 +114,8 @@ namespace boost { namespace spirit { namespace qi
Subject subject;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- attr_cast_parser& operator= (attr_cast_parser const&);
+ BOOST_DELETED_FUNCTION(attr_cast_parser& operator= (attr_cast_parser const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/qi/detail/alternative_function.hpp b/boost/spirit/home/qi/detail/alternative_function.hpp
index aeb6314fb4..347cd1a442 100644
--- a/boost/spirit/home/qi/detail/alternative_function.hpp
+++ b/boost/spirit/home/qi/detail/alternative_function.hpp
@@ -174,9 +174,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
Skipper const& skipper;
Attribute& attr;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- alternative_function& operator= (alternative_function const&);
+ BOOST_DELETED_FUNCTION(alternative_function& operator= (alternative_function const&))
};
template <typename Iterator, typename Context, typename Skipper>
@@ -202,9 +201,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
Context& context;
Skipper const& skipper;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- alternative_function& operator= (alternative_function const&);
+ BOOST_DELETED_FUNCTION(alternative_function& operator= (alternative_function const&))
};
}}}}
diff --git a/boost/spirit/home/qi/detail/expect_function.hpp b/boost/spirit/home/qi/detail/expect_function.hpp
index 920e30997b..ee45ae4dbf 100644
--- a/boost/spirit/home/qi/detail/expect_function.hpp
+++ b/boost/spirit/home/qi/detail/expect_function.hpp
@@ -96,9 +96,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
Skipper const& skipper;
mutable bool is_first;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- expect_function& operator= (expect_function const&);
+ BOOST_DELETED_FUNCTION(expect_function& operator= (expect_function const&))
};
}}}}
diff --git a/boost/spirit/home/qi/detail/fail_function.hpp b/boost/spirit/home/qi/detail/fail_function.hpp
index 7ab8d82a2b..fa090da3ee 100644
--- a/boost/spirit/home/qi/detail/fail_function.hpp
+++ b/boost/spirit/home/qi/detail/fail_function.hpp
@@ -50,9 +50,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
Context& context;
Skipper const& skipper;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- fail_function& operator= (fail_function const&);
+ BOOST_DELETED_FUNCTION(fail_function& operator= (fail_function const&))
};
}}}}
diff --git a/boost/spirit/home/qi/detail/pass_container.hpp b/boost/spirit/home/qi/detail/pass_container.hpp
index f41f1e9bcc..35de5410b0 100644
--- a/boost/spirit/home/qi/detail/pass_container.hpp
+++ b/boost/spirit/home/qi/detail/pass_container.hpp
@@ -354,9 +354,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
F f;
Attr& attr;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- pass_container& operator= (pass_container const&);
+ BOOST_DELETED_FUNCTION(pass_container& operator= (pass_container const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/qi/detail/pass_function.hpp b/boost/spirit/home/qi/detail/pass_function.hpp
index 555adb8a49..4c80526309 100644
--- a/boost/spirit/home/qi/detail/pass_function.hpp
+++ b/boost/spirit/home/qi/detail/pass_function.hpp
@@ -61,9 +61,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
Context& context;
Skipper const& skipper;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- pass_function& operator= (pass_function const&);
+ BOOST_DELETED_FUNCTION(pass_function& operator= (pass_function const&))
};
}}}}
diff --git a/boost/spirit/home/qi/detail/permute_function.hpp b/boost/spirit/home/qi/detail/permute_function.hpp
index 4366568eb8..b098c03078 100644
--- a/boost/spirit/home/qi/detail/permute_function.hpp
+++ b/boost/spirit/home/qi/detail/permute_function.hpp
@@ -63,9 +63,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
Skipper const& skipper;
bool* taken;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- permute_function& operator= (permute_function const&);
+ BOOST_DELETED_FUNCTION(permute_function& operator= (permute_function const&))
};
}}}}
diff --git a/boost/spirit/home/qi/detail/unused_skipper.hpp b/boost/spirit/home/qi/detail/unused_skipper.hpp
index b8a51f3224..f8b6bf9984 100644
--- a/boost/spirit/home/qi/detail/unused_skipper.hpp
+++ b/boost/spirit/home/qi/detail/unused_skipper.hpp
@@ -22,9 +22,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
: skipper(skipper_) {}
Skipper const& skipper;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- unused_skipper& operator= (unused_skipper const&);
+ BOOST_DELETED_FUNCTION(unused_skipper& operator= (unused_skipper const&))
};
template <typename Skipper>
diff --git a/boost/spirit/home/qi/directive/matches.hpp b/boost/spirit/home/qi/directive/matches.hpp
index b6fecb994d..d815f76731 100644
--- a/boost/spirit/home/qi/directive/matches.hpp
+++ b/boost/spirit/home/qi/directive/matches.hpp
@@ -71,9 +71,8 @@ namespace boost { namespace spirit { namespace qi
Subject subject;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- matches_directive& operator= (matches_directive const&);
+ BOOST_DELETED_FUNCTION(matches_directive& operator= (matches_directive const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/qi/directive/omit.hpp b/boost/spirit/home/qi/directive/omit.hpp
index 05a6a76d75..1d3f4afb99 100644
--- a/boost/spirit/home/qi/directive/omit.hpp
+++ b/boost/spirit/home/qi/directive/omit.hpp
@@ -70,9 +70,8 @@ namespace boost { namespace spirit { namespace qi
Subject subject;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- omit_directive& operator= (omit_directive const&);
+ BOOST_DELETED_FUNCTION(omit_directive& operator= (omit_directive const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/qi/directive/repeat.hpp b/boost/spirit/home/qi/directive/repeat.hpp
index 72c3a998be..429083a228 100644
--- a/boost/spirit/home/qi/directive/repeat.hpp
+++ b/boost/spirit/home/qi/directive/repeat.hpp
@@ -91,9 +91,8 @@ namespace boost { namespace spirit { namespace qi
T const exact;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- exact_iterator& operator= (exact_iterator const&);
+ BOOST_DELETED_FUNCTION(exact_iterator& operator= (exact_iterator const&))
};
template <typename T>
@@ -111,9 +110,8 @@ namespace boost { namespace spirit { namespace qi
T const min;
T const max;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- finite_iterator& operator= (finite_iterator const&);
+ BOOST_DELETED_FUNCTION(finite_iterator& operator= (finite_iterator const&))
};
template <typename T>
@@ -129,9 +127,8 @@ namespace boost { namespace spirit { namespace qi
T const min;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- infinite_iterator& operator= (infinite_iterator const&);
+ BOOST_DELETED_FUNCTION(infinite_iterator& operator= (infinite_iterator const&))
};
template <typename Subject, typename LoopIter>
@@ -209,9 +206,8 @@ namespace boost { namespace spirit { namespace qi
Subject subject;
LoopIter iter;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- repeat_parser& operator= (repeat_parser const&);
+ BOOST_DELETED_FUNCTION(repeat_parser& operator= (repeat_parser const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/qi/numeric/detail/real_impl.hpp b/boost/spirit/home/qi/numeric/detail/real_impl.hpp
index 43a51dae8a..7ae9f0b10d 100644
--- a/boost/spirit/home/qi/numeric/detail/real_impl.hpp
+++ b/boost/spirit/home/qi/numeric/detail/real_impl.hpp
@@ -1,5 +1,5 @@
/*=============================================================================
- Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2019 Joel de Guzman
Copyright (c) 2001-2011 Hartmut Kaiser
http://spirit.sourceforge.net/
@@ -65,11 +65,11 @@ namespace boost { namespace spirit { namespace traits
{
if (exp >= 0)
{
- int max_exp = std::numeric_limits<T>::max_exponent10;
+ int const max_exp = std::numeric_limits<T>::max_exponent10;
// return false if exp exceeds the max_exp
// do this check only for primitive types!
- if (is_floating_point<T>() && exp > max_exp)
+ if (is_floating_point<T>() && (exp > max_exp))
return false;
n = acc_n * pow10<T>(exp);
}
@@ -77,7 +77,7 @@ namespace boost { namespace spirit { namespace traits
{
if (exp < std::numeric_limits<T>::min_exponent10)
{
- int min_exp = std::numeric_limits<T>::min_exponent10;
+ int const min_exp = std::numeric_limits<T>::min_exponent10;
detail::compensate_roundoff(n, acc_n);
n /= pow10<T>(-min_exp);
@@ -164,9 +164,33 @@ namespace boost { namespace spirit { namespace traits
namespace boost { namespace spirit { namespace qi { namespace detail
{
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(version)
+
template <typename T, typename RealPolicies>
struct real_impl
{
+ template <typename Iterator>
+ static std::size_t
+ ignore_excess_digits(Iterator& first, Iterator const& last, mpl::false_)
+ {
+ return 0;
+ }
+
+ template <typename Iterator>
+ static std::size_t
+ ignore_excess_digits(Iterator& first, Iterator const& last, mpl::true_)
+ {
+ return RealPolicies::ignore_excess_digits(first, last);
+ }
+
+ template <typename Iterator>
+ static std::size_t
+ ignore_excess_digits(Iterator& first, Iterator const& last)
+ {
+ typedef mpl::bool_<has_version<RealPolicies>::value> has_version;
+ return ignore_excess_digits(first, last, has_version());
+ }
+
template <typename Iterator, typename Attribute>
static bool
parse(Iterator& first, Iterator const& last, Attribute& attr,
@@ -185,6 +209,7 @@ namespace boost { namespace spirit { namespace qi { namespace detail
typename traits::real_accumulator<T>::type acc_n = 0;
bool got_a_number = p.parse_n(first, last, acc_n);
+ int excess_n = 0;
// If we did not get a number it might be a NaN, Inf or a leading
// dot.
@@ -207,6 +232,12 @@ namespace boost { namespace spirit { namespace qi { namespace detail
return false;
}
}
+ else
+ {
+ // We got a number and we still see digits. This happens if acc_n (an integer)
+ // exceeds the integer's capacity. Collect the excess digits.
+ excess_n = static_cast<int>(ignore_excess_digits(first, last));
+ }
bool e_hit = false;
Iterator e_pos;
@@ -218,7 +249,12 @@ namespace boost { namespace spirit { namespace qi { namespace detail
// We got the decimal point. Now we will try to parse
// the fraction if it is there. If not, it defaults
// to zero (0) only if we already got a number.
- if (p.parse_frac_n(first, last, acc_n, frac_digits))
+ if (excess_n != 0)
+ {
+ // We skip the fractions if we already exceeded our digits capacity
+ ignore_excess_digits(first, last);
+ }
+ else if (p.parse_frac_n(first, last, acc_n, frac_digits))
{
BOOST_ASSERT(frac_digits >= 0);
}
@@ -263,8 +299,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
if (p.parse_exp_n(first, last, exp))
{
// Got the exponent value. Scale the number by
- // exp-frac_digits.
- if (!traits::scale(exp, frac_digits, n, acc_n))
+ // exp + excess_n - frac_digits.
+ if (!traits::scale(exp + excess_n, frac_digits, n, acc_n))
return false;
}
else
@@ -285,7 +321,15 @@ namespace boost { namespace spirit { namespace qi { namespace detail
}
else
{
- n = static_cast<T>(acc_n);
+ if (excess_n)
+ {
+ if (!traits::scale(excess_n, n, acc_n))
+ return false;
+ }
+ else
+ {
+ n = static_cast<T>(acc_n);
+ }
}
// If we got a negative sign, negate the number
diff --git a/boost/spirit/home/qi/numeric/real_policies.hpp b/boost/spirit/home/qi/numeric/real_policies.hpp
index 48cf2b97a5..185a108b8b 100644
--- a/boost/spirit/home/qi/numeric/real_policies.hpp
+++ b/boost/spirit/home/qi/numeric/real_policies.hpp
@@ -1,5 +1,5 @@
/*=============================================================================
- Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2019 Joel de Guzman
Copyright (c) 2001-2011 Hartmut Kaiser
Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -14,6 +14,29 @@
#include <boost/spirit/home/qi/numeric/numeric_utils.hpp>
#include <boost/spirit/home/qi/detail/string_parse.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+
+namespace boost { namespace spirit { namespace traits
+{
+ // So that we won't exceed the capacity of the underlying type T,
+ // we limit the number of digits parsed to its max_digits10.
+ // By default, the value is -1 which tells spirit to parse an
+ // unbounded number of digits.
+
+ template <typename T, typename Enable = void>
+ struct max_digits10
+ {
+ static int const value = -1; // unbounded
+ };
+
+ template <typename T>
+ struct max_digits10<T
+ , typename enable_if_c<(is_floating_point<T>::value)>::type>
+ {
+ static int const digits = std::numeric_limits<T>::digits;
+ static int const value = 2 + (digits * 30103l) / 100000l;
+ };
+}}}
namespace boost { namespace spirit { namespace qi
{
@@ -23,6 +46,9 @@ namespace boost { namespace spirit { namespace qi
template <typename T>
struct ureal_policies
{
+ // Versioning
+ typedef mpl::int_<2> version;
+
// trailing dot policy suggested by Gustavo Guerra
static bool const allow_leading_dot = true;
static bool const allow_trailing_dot = true;
@@ -39,7 +65,22 @@ namespace boost { namespace spirit { namespace qi
static bool
parse_n(Iterator& first, Iterator const& last, Attribute& attr_)
{
- return extract_uint<Attribute, 10, 1, -1>::call(first, last, attr_);
+ typedef extract_uint<Attribute, 10, 1
+ , traits::max_digits10<T>::value // See notes on max_digits10 above
+ , false, true>
+ extract_uint;
+ return extract_uint::call(first, last, attr_);
+ }
+
+ // ignore_excess_digits (required for version > 1 API)
+ template <typename Iterator>
+ static std::size_t
+ ignore_excess_digits(Iterator& first, Iterator const& last)
+ {
+ Iterator save = first;
+ if (extract_uint<unused_type, 10, 1, -1>::call(first, last, unused))
+ return std::distance(save, first);
+ return 0;
}
template <typename Iterator>
diff --git a/boost/spirit/home/qi/stream/detail/iterator_source.hpp b/boost/spirit/home/qi/stream/detail/iterator_source.hpp
index abb7fe028b..7bc63ea054 100644
--- a/boost/spirit/home/qi/stream/detail/iterator_source.hpp
+++ b/boost/spirit/home/qi/stream/detail/iterator_source.hpp
@@ -69,9 +69,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
Iterator const& last;
std::streamsize pos;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- base_iterator_source& operator= (base_iterator_source const&);
+ BOOST_DELETED_FUNCTION(base_iterator_source& operator= (base_iterator_source const&))
};
template <typename Iterator, typename Enable = void>
diff --git a/boost/spirit/home/qi/stream/detail/match_manip.hpp b/boost/spirit/home/qi/stream/detail/match_manip.hpp
index e74bdcfc91..850e6040d7 100644
--- a/boost/spirit/home/qi/stream/detail/match_manip.hpp
+++ b/boost/spirit/home/qi/stream/detail/match_manip.hpp
@@ -46,9 +46,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
Attribute& attr;
BOOST_SCOPED_ENUM(skip_flag) const post_skip;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- match_manip& operator= (match_manip const&);
+ BOOST_DELETED_FUNCTION(match_manip& operator= (match_manip const&))
};
template <typename Expr, typename Skipper, typename Attribute>
@@ -66,9 +65,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
Attribute attr;
BOOST_SCOPED_ENUM(skip_flag) const post_skip;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- match_manip& operator= (match_manip const&);
+ BOOST_DELETED_FUNCTION(match_manip& operator= (match_manip const&))
};
template <typename Expr, typename Skipper, typename Attribute>
@@ -86,9 +84,8 @@ namespace boost { namespace spirit { namespace qi { namespace detail
Attribute& attr;
BOOST_SCOPED_ENUM(skip_flag) const post_skip;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- match_manip& operator= (match_manip const&);
+ BOOST_DELETED_FUNCTION(match_manip& operator= (match_manip const&))
};
///////////////////////////////////////////////////////////////////////////
diff --git a/boost/spirit/home/qi/string/lit.hpp b/boost/spirit/home/qi/string/lit.hpp
index 1e163619c9..25fdf504ff 100644
--- a/boost/spirit/home/qi/string/lit.hpp
+++ b/boost/spirit/home/qi/string/lit.hpp
@@ -118,9 +118,8 @@ namespace boost { namespace spirit { namespace qi
String str;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- literal_string& operator= (literal_string const&);
+ BOOST_DELETED_FUNCTION(literal_string& operator= (literal_string const&))
};
template <typename String, bool no_attribute>
diff --git a/boost/spirit/home/qi/string/symbols.hpp b/boost/spirit/home/qi/string/symbols.hpp
index e54a3c6558..c688d80cae 100644
--- a/boost/spirit/home/qi/string/symbols.hpp
+++ b/boost/spirit/home/qi/string/symbols.hpp
@@ -322,9 +322,8 @@ public:
symbols& sym;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- adder& operator= (adder const&);
+ BOOST_DELETED_FUNCTION(adder& operator= (adder const&))
};
struct remover
@@ -365,9 +364,8 @@ public:
symbols& sym;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- remover& operator= (remover const&);
+ BOOST_DELETED_FUNCTION(remover& operator= (remover const&))
};
adder add;
diff --git a/boost/spirit/home/support/detail/hold_any.hpp b/boost/spirit/home/support/detail/hold_any.hpp
index d8b08dc1ee..2c874e7b8c 100644
--- a/boost/spirit/home/support/detail/hold_any.hpp
+++ b/boost/spirit/home/support/detail/hold_any.hpp
@@ -25,7 +25,7 @@
#include <boost/static_assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/assert.hpp>
-#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/core/typeinfo.hpp>
#include <stdexcept>
#include <typeinfo>
@@ -45,7 +45,7 @@ namespace boost { namespace spirit
struct bad_any_cast
: std::bad_cast
{
- bad_any_cast(boost::detail::sp_typeinfo const& src, boost::detail::sp_typeinfo const& dest)
+ bad_any_cast(boost::core::typeinfo const& src, boost::core::typeinfo const& dest)
: from(src.name()), to(dest.name())
{}
@@ -61,7 +61,7 @@ namespace boost { namespace spirit
template <typename Char>
struct fxn_ptr_table
{
- boost::detail::sp_typeinfo const& (*get_type)();
+ boost::core::typeinfo const& (*get_type)();
void (*static_delete)(void**);
void (*destruct)(void**);
void (*clone)(void* const*, void**);
@@ -80,9 +80,9 @@ namespace boost { namespace spirit
template<typename T, typename Char>
struct type
{
- static boost::detail::sp_typeinfo const& get_type()
+ static boost::core::typeinfo const& get_type()
{
- return BOOST_SP_TYPEID(T);
+ return BOOST_CORE_TYPEID(T);
}
static void static_delete(void** x)
{
@@ -123,9 +123,9 @@ namespace boost { namespace spirit
template<typename T, typename Char>
struct type
{
- static boost::detail::sp_typeinfo const& get_type()
+ static boost::core::typeinfo const& get_type()
{
- return BOOST_SP_TYPEID(T);
+ return BOOST_CORE_TYPEID(T);
}
static void static_delete(void** x)
{
@@ -341,7 +341,7 @@ namespace boost { namespace spirit
return *this;
}
- boost::detail::sp_typeinfo const& type() const
+ boost::core::typeinfo const& type() const
{
return table->get_type();
}
@@ -349,8 +349,8 @@ namespace boost { namespace spirit
template <typename T>
T const& cast() const
{
- if (type() != BOOST_SP_TYPEID(T))
- throw bad_any_cast(type(), BOOST_SP_TYPEID(T));
+ if (type() != BOOST_CORE_TYPEID(T))
+ throw bad_any_cast(type(), BOOST_CORE_TYPEID(T));
return spirit::detail::get_table<T>::is_small::value ?
*reinterpret_cast<T const*>(&object) :
@@ -413,7 +413,7 @@ namespace boost { namespace spirit
template <typename T, typename Char>
inline T* any_cast (basic_hold_any<Char>* operand)
{
- if (operand && operand->type() == BOOST_SP_TYPEID(T)) {
+ if (operand && operand->type() == BOOST_CORE_TYPEID(T)) {
return spirit::detail::get_table<T>::is_small::value ?
reinterpret_cast<T*>(&operand->object) :
reinterpret_cast<T*>(operand->object);
@@ -435,7 +435,7 @@ namespace boost { namespace spirit
nonref* result = any_cast<nonref>(&operand);
if(!result)
- boost::throw_exception(bad_any_cast(operand.type(), BOOST_SP_TYPEID(T)));
+ boost::throw_exception(bad_any_cast(operand.type(), BOOST_CORE_TYPEID(T)));
return *result;
}
diff --git a/boost/spirit/home/support/detail/what_function.hpp b/boost/spirit/home/support/detail/what_function.hpp
index 179807b1ac..575dbaac0f 100644
--- a/boost/spirit/home/support/detail/what_function.hpp
+++ b/boost/spirit/home/support/detail/what_function.hpp
@@ -39,9 +39,8 @@ namespace boost { namespace spirit { namespace detail
info& what;
Context& context;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- what_function& operator= (what_function const&);
+ BOOST_DELETED_FUNCTION(what_function& operator= (what_function const&))
};
}}}
diff --git a/boost/spirit/home/support/info.hpp b/boost/spirit/home/support/info.hpp
index 9b991ac882..0557bd9b62 100644
--- a/boost/spirit/home/support/info.hpp
+++ b/boost/spirit/home/support/info.hpp
@@ -117,9 +117,8 @@ namespace boost { namespace spirit
utf8_string const& tag;
int depth;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- basic_info_walker& operator= (basic_info_walker const&);
+ BOOST_DELETED_FUNCTION(basic_info_walker& operator= (basic_info_walker const&))
};
// bare-bones print support
@@ -141,9 +140,8 @@ namespace boost { namespace spirit
Out& out;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- simple_printer& operator= (simple_printer const&);
+ BOOST_DELETED_FUNCTION(simple_printer& operator= (simple_printer const&))
};
template <typename Out>
diff --git a/boost/spirit/home/support/iterators/detail/split_functor_input_policy.hpp b/boost/spirit/home/support/iterators/detail/split_functor_input_policy.hpp
index 711ae90394..b92cc861db 100644
--- a/boost/spirit/home/support/iterators/detail/split_functor_input_policy.hpp
+++ b/boost/spirit/home/support/iterators/detail/split_functor_input_policy.hpp
@@ -190,9 +190,8 @@ namespace boost { namespace spirit { namespace iterator_policies
mutable typename Functor::second_type ftor;
result_type curtok;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- shared& operator= (shared const&);
+ BOOST_DELETED_FUNCTION(shared& operator= (shared const&))
};
};
diff --git a/boost/spirit/home/support/nonterminal/expand_arg.hpp b/boost/spirit/home/support/nonterminal/expand_arg.hpp
index f214096be1..12b0c88750 100644
--- a/boost/spirit/home/support/nonterminal/expand_arg.hpp
+++ b/boost/spirit/home/support/nonterminal/expand_arg.hpp
@@ -78,9 +78,8 @@ namespace boost { namespace spirit { namespace detail
Context& context;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- expand_arg& operator= (expand_arg const&);
+ BOOST_DELETED_FUNCTION(expand_arg& operator= (expand_arg const&))
};
}}}
diff --git a/boost/spirit/home/support/terminal.hpp b/boost/spirit/home/support/terminal.hpp
index dd52da9c25..08e21236f3 100644
--- a/boost/spirit/home/support/terminal.hpp
+++ b/boost/spirit/home/support/terminal.hpp
@@ -485,9 +485,8 @@ namespace boost { namespace spirit
, phoenix::as_actor<A2>::convert(_2_));
}
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- terminal& operator= (terminal const&);
+ BOOST_DELETED_FUNCTION(terminal& operator= (terminal const&))
};
///////////////////////////////////////////////////////////////////////////
@@ -543,9 +542,8 @@ namespace boost { namespace spirit
data_type data_;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- stateful_tag& operator= (stateful_tag const&);
+ BOOST_DELETED_FUNCTION(stateful_tag& operator= (stateful_tag const&))
};
}
@@ -562,9 +560,8 @@ namespace boost { namespace spirit
: spirit::terminal<tag_type>(data)
{}
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- stateful_tag_type& operator= (stateful_tag_type const&);
+ BOOST_DELETED_FUNCTION(stateful_tag_type& operator= (stateful_tag_type const&))
};
namespace detail
diff --git a/boost/spirit/home/support/unused.hpp b/boost/spirit/home/support/unused.hpp
index 4197d6af57..4ffad6b09b 100644
--- a/boost/spirit/home/support/unused.hpp
+++ b/boost/spirit/home/support/unused.hpp
@@ -15,11 +15,6 @@
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
-#if defined(BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable: 4522) // multiple assignment operators specified warning
-#endif
-
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
@@ -31,9 +26,7 @@ namespace boost { namespace spirit
///////////////////////////////////////////////////////////////////////////
struct unused_type
{
- unused_type()
- {
- }
+ BOOST_DEFAULTED_FUNCTION(unused_type(), {})
template <typename T>
unused_type(T const&)
@@ -53,18 +46,6 @@ namespace boost { namespace spirit
{
return *this;
}
-
- unused_type const&
- operator=(unused_type const&) const
- {
- return *this;
- }
-
- unused_type&
- operator=(unused_type const&)
- {
- return *this;
- }
};
unused_type const unused = unused_type();
@@ -98,8 +79,4 @@ namespace boost { namespace spirit
}
}}
-#if defined(BOOST_MSVC)
-# pragma warning(pop)
-#endif
-
#endif
diff --git a/boost/spirit/home/support/utree/detail/utree_detail2.hpp b/boost/spirit/home/support/utree/detail/utree_detail2.hpp
index ff6dd76e7b..ef309d343b 100644
--- a/boost/spirit/home/support/utree/detail/utree_detail2.hpp
+++ b/boost/spirit/home/support/utree/detail/utree_detail2.hpp
@@ -19,6 +19,7 @@
#include <boost/utility/enable_if.hpp>
#include <boost/throw_exception.hpp>
#include <boost/iterator/iterator_traits.hpp>
+#include <cstring> // for std::memcpy
namespace boost { namespace spirit { namespace detail
{
diff --git a/boost/spirit/home/x3/auxiliary/attr.hpp b/boost/spirit/home/x3/auxiliary/attr.hpp
index 6471bd90df..0459e55255 100644
--- a/boost/spirit/home/x3/auxiliary/attr.hpp
+++ b/boost/spirit/home/x3/auxiliary/attr.hpp
@@ -50,9 +50,8 @@ namespace boost { namespace spirit { namespace x3
Value value_;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- attr_parser& operator= (attr_parser const&);
+ attr_parser& operator= (attr_parser const&) = delete;
};
template <typename Value, std::size_t N>
@@ -86,9 +85,8 @@ namespace boost { namespace spirit { namespace x3
Value value_[N];
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- attr_parser& operator= (attr_parser const&);
+ attr_parser& operator= (attr_parser const&) = delete;
};
template <typename Value>
diff --git a/boost/spirit/home/x3/char/char_set.hpp b/boost/spirit/home/x3/char/char_set.hpp
index 26e15478dc..082f6ce191 100644
--- a/boost/spirit/home/x3/char/char_set.hpp
+++ b/boost/spirit/home/x3/char/char_set.hpp
@@ -67,18 +67,11 @@ namespace boost { namespace spirit { namespace x3
{
using spirit::x3::detail::cast_char;
- typedef typename
- remove_const<
- typename traits::char_type_of<String>::type
- >::type
- in_type;
-
- in_type const* definition =
- (in_type const*)traits::get_c_string(str);
- in_type ch = *definition++;
+ auto* definition = traits::get_c_string(str);
+ auto ch = *definition++;
while (ch)
{
- in_type next = *definition++;
+ auto next = *definition++;
if (next == '-')
{
next = *definition++;
diff --git a/boost/spirit/home/x3/char/unicode.hpp b/boost/spirit/home/x3/char/unicode.hpp
index 290c7a4adc..a7bcbfb205 100644
--- a/boost/spirit/home/x3/char/unicode.hpp
+++ b/boost/spirit/home/x3/char/unicode.hpp
@@ -197,26 +197,26 @@ namespace boost { namespace spirit { namespace x3
typedef char_encoding::unicode encoding;
typedef char_encoding::unicode::char_type char_type;
-#define BOOST_SPIRIT_X3_BASIC_CLASSIFY(name) \
- template <typename Char> \
- static bool \
- is(name##_tag, Char ch) \
- { \
- return encoding::is ##name \
- BOOST_PREVENT_MACRO_SUBSTITUTION \
- (detail::cast_char<char_type>(ch)); \
- } \
+#define BOOST_SPIRIT_X3_BASIC_CLASSIFY(name) \
+ template <typename Char> \
+ static bool \
+ is(name##_tag, Char ch) \
+ { \
+ return encoding::is ##name \
+ BOOST_PREVENT_MACRO_SUBSTITUTION \
+ (detail::cast_char<char_type>(ch)); \
+ } \
/***/
-#define BOOST_SPIRIT_X3_CLASSIFY(name) \
- template <typename Char> \
- static bool \
- is(name##_tag, Char ch) \
- { \
- return encoding::is_##name \
- BOOST_PREVENT_MACRO_SUBSTITUTION \
- (detail::cast_char<char_type>(ch)); \
- } \
+#define BOOST_SPIRIT_X3_CLASSIFY(name) \
+ template <typename Char> \
+ static bool \
+ is(name##_tag, Char ch) \
+ { \
+ return encoding::is_##name \
+ BOOST_PREVENT_MACRO_SUBSTITUTION \
+ (detail::cast_char<char_type>(ch)); \
+ } \
/***/
@@ -419,9 +419,9 @@ namespace boost { namespace spirit { namespace x3
}
};
-#define BOOST_SPIRIT_X3_CHAR_CLASS(name) \
- typedef unicode_char_class<name##_tag> name##_type; \
- name##_type const name = name##_type(); \
+#define BOOST_SPIRIT_X3_CHAR_CLASS(name) \
+ typedef unicode_char_class<name##_tag> name##_type; \
+ name##_type const name = name##_type(); \
/***/
namespace unicode
diff --git a/boost/spirit/home/x3/core/detail/parse_into_container.hpp b/boost/spirit/home/x3/core/detail/parse_into_container.hpp
index 979238cff3..b58add3b28 100644
--- a/boost/spirit/home/x3/core/detail/parse_into_container.hpp
+++ b/boost/spirit/home/x3/core/detail/parse_into_container.hpp
@@ -12,6 +12,7 @@
#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
#include <boost/spirit/home/x3/support/traits/value_traits.hpp>
#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
+#include <boost/spirit/home/x3/support/traits/pseudo_attribute.hpp>
#include <boost/spirit/home/x3/support/traits/handles_container.hpp>
#include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
#include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
@@ -91,10 +92,10 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
, Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
{
// synthesized attribute needs to be value initialized
- typedef typename
- traits::container_value<Attribute>::type
- value_type;
- value_type val = traits::value_initialize<value_type>::call();
+ using value_type = typename traits::container_value<Attribute>::type;
+ using pseudo = traits::pseudo_attribute<Context, value_type, Iterator>;
+ typename pseudo::type val = pseudo::call(
+ first, last, traits::value_initialize<value_type>::call());
if (!parser.parse(first, last, context, rcontext, val))
return false;
@@ -221,10 +222,14 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
template <typename Parser, typename Context, typename RContext, typename Enable = void>
struct parse_into_container_impl : parse_into_container_base_impl<Parser> {};
- template <typename Parser, typename Container, typename Context>
+ template <typename Parser, typename Iterator, typename Container, typename Context>
struct parser_attr_is_substitute_for_container_value
: traits::is_substitute<
- typename traits::attribute_of<Parser, Context>::type
+ typename traits::pseudo_attribute<
+ Context
+ , typename traits::attribute_of<Parser, Context>::type
+ , Iterator
+ >::type
, typename traits::container_value<Container>::type
>
{};
@@ -278,7 +283,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
parser_accepts_container;
typedef parser_attr_is_substitute_for_container_value<
- Parser, Attribute, Context>
+ Parser, Iterator, Attribute, Context>
parser_attr_is_substitute_for_container_value;
typedef mpl::or_<
diff --git a/boost/spirit/home/x3/directive/raw.hpp b/boost/spirit/home/x3/directive/raw.hpp
index 8432e13888..2f82362544 100644
--- a/boost/spirit/home/x3/directive/raw.hpp
+++ b/boost/spirit/home/x3/directive/raw.hpp
@@ -10,6 +10,7 @@
#include <boost/spirit/home/x3/core/skip_over.hpp>
#include <boost/spirit/home/x3/core/parser.hpp>
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
+#include <boost/spirit/home/x3/support/traits/pseudo_attribute.hpp>
#include <boost/range/iterator_range.hpp>
namespace boost { namespace spirit { namespace x3
@@ -65,6 +66,21 @@ namespace boost { namespace spirit { namespace x3
};
auto const raw = raw_gen{};
+
+ namespace traits
+ {
+ template <typename Context, typename Iterator>
+ struct pseudo_attribute<Context, raw_attribute_type, Iterator>
+ {
+ using attribute_type = raw_attribute_type;
+ using type = boost::iterator_range<Iterator>;
+
+ static type call(Iterator& first, Iterator const& last, attribute_type)
+ {
+ return { first, last };
+ }
+ };
+ }
}}}
#endif
diff --git a/boost/spirit/home/x3/nonterminal/rule.hpp b/boost/spirit/home/x3/nonterminal/rule.hpp
index 2aee90f551..73f4ec6436 100644
--- a/boost/spirit/home/x3/nonterminal/rule.hpp
+++ b/boost/spirit/home/x3/nonterminal/rule.hpp
@@ -131,9 +131,6 @@ namespace boost { namespace spirit { namespace x3
bool parse(Iterator& first, Iterator const& last
, Context const& context, unused_type, unused_type) const
{
- static_assert(!has_attribute,
- "The rule requires an input attribute. Check your parser.");
-
// make sure we pass exactly the rule attribute type
attribute_type no_attr;
return parse_rule(*this, first, last, context, no_attr);
diff --git a/boost/spirit/home/x3/numeric/real.hpp b/boost/spirit/home/x3/numeric/real.hpp
index a7a9573058..a90543fc69 100644
--- a/boost/spirit/home/x3/numeric/real.hpp
+++ b/boost/spirit/home/x3/numeric/real.hpp
@@ -57,6 +57,9 @@ namespace boost { namespace spirit { namespace x3
typedef real_parser<double> double_type;
double_type const double_ = {};
+ typedef real_parser<long double> long_double_type;
+ long_double_type const long_double = {};
+
}}}
#endif
diff --git a/boost/spirit/home/x3/operator/detail/alternative.hpp b/boost/spirit/home/x3/operator/detail/alternative.hpp
index 2c87fa0376..e66a76e3be 100644
--- a/boost/spirit/home/x3/operator/detail/alternative.hpp
+++ b/boost/spirit/home/x3/operator/detail/alternative.hpp
@@ -8,6 +8,7 @@
#define BOOST_SPIRIT_X3_ALTERNATIVE_DETAIL_JAN_07_2013_1245PM
#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
+#include <boost/spirit/home/x3/support/traits/pseudo_attribute.hpp>
#include <boost/spirit/home/x3/support/traits/is_variant.hpp>
#include <boost/spirit/home/x3/support/traits/tuple_traits.hpp>
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
@@ -244,9 +245,11 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
bool parse_alternative(Parser const& p, Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr)
{
- typedef detail::pass_variant_attribute<Parser, Attribute, Context> pass;
+ using pass = detail::pass_variant_attribute<Parser, Attribute, Context>;
+ using pseudo = traits::pseudo_attribute<Context, typename pass::type, Iterator>;
+
+ typename pseudo::type attr_ = pseudo::call(first, last, pass::call(attr));
- typename pass::type attr_ = pass::call(attr);
if (p.parse(first, last, context, rcontext, attr_))
{
move_if_not_alternative<typename pass::is_alternative>::call(attr_, attr);
@@ -255,7 +258,6 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
return false;
}
-
template <typename Left, typename Right, typename Context, typename RContext>
struct parse_into_container_impl<alternative<Left, Right>, Context, RContext>
{
diff --git a/boost/spirit/home/x3/operator/detail/sequence.hpp b/boost/spirit/home/x3/operator/detail/sequence.hpp
index 9d3fe5c992..3ac21b61c9 100644
--- a/boost/spirit/home/x3/operator/detail/sequence.hpp
+++ b/boost/spirit/home/x3/operator/detail/sequence.hpp
@@ -304,11 +304,11 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
, Context const& context, RContext& rcontext, Attribute& attr
, AttributeCategory)
{
- typedef typename Parser::left_type Left;
- typedef typename Parser::right_type Right;
- typedef partition_attribute<Left, Right, Attribute, Context> partition;
- typedef typename partition::l_pass l_pass;
- typedef typename partition::r_pass r_pass;
+ using Left = typename Parser::left_type;
+ using Right = typename Parser::right_type;
+ using partition = partition_attribute<Left, Right, Attribute, Context>;
+ using l_pass = typename partition::l_pass;
+ using r_pass = typename partition::r_pass;
typename partition::l_part l_part = partition::left(attr);
typename partition::r_part r_part = partition::right(attr);
diff --git a/boost/spirit/home/x3/string/literal_string.hpp b/boost/spirit/home/x3/string/literal_string.hpp
index 486dc807b3..55ed567368 100644
--- a/boost/spirit/home/x3/string/literal_string.hpp
+++ b/boost/spirit/home/x3/string/literal_string.hpp
@@ -106,6 +106,35 @@ namespace boost { namespace spirit { namespace x3
}
#endif
+#if defined(BOOST_SPIRIT_X3_UNICODE)
+ namespace unicode
+ {
+ inline literal_string<char32_t const*, char_encoding::unicode>
+ string(char32_t const* s)
+ {
+ return { s };
+ }
+
+ inline literal_string<std::basic_string<char32_t>, char_encoding::unicode>
+ string(std::basic_string<char32_t> const& s)
+ {
+ return { s };
+ }
+
+ inline literal_string<char32_t const*, char_encoding::unicode, unused_type>
+ lit(char32_t const* s)
+ {
+ return { s };
+ }
+
+ inline literal_string<std::basic_string<char32_t>, char_encoding::unicode, unused_type>
+ lit(std::basic_string<char32_t> const& s)
+ {
+ return { s };
+ }
+ }
+#endif
+
namespace ascii
{
inline literal_string<wchar_t const*, char_encoding::ascii>
diff --git a/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp b/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp
index fb5cd4d069..91b71e9829 100644
--- a/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp
+++ b/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp
@@ -29,47 +29,61 @@ namespace boost { namespace spirit { namespace x3 { namespace extension
using x3::traits::pow10;
template <typename T>
- inline void
+ inline bool
scale(int exp, T& n)
{
+ constexpr auto max_exp = std::numeric_limits<T>::max_exponent10;
+ constexpr auto min_exp = std::numeric_limits<T>::min_exponent10;
+
if (exp >= 0)
{
- // $$$ Why is this failing for boost.math.concepts ? $$$
- //~ int nn = std::numeric_limits<T>::max_exponent10;
- //~ BOOST_ASSERT(exp <= std::numeric_limits<T>::max_exponent10);
+ // return false if exp exceeds the max_exp
+ // do this check only for primitive types!
+ if (is_floating_point<T>() && exp > max_exp)
+ return false;
n *= pow10<T>(exp);
}
else
{
- if (exp < std::numeric_limits<T>::min_exponent10)
+ if (exp < min_exp)
{
- n /= pow10<T>(-std::numeric_limits<T>::min_exponent10);
- n /= pow10<T>(-exp + std::numeric_limits<T>::min_exponent10);
+ n /= pow10<T>(-min_exp);
+
+ // return false if exp still exceeds the min_exp
+ // do this check only for primitive types!
+ exp += -min_exp;
+ if (is_floating_point<T>() && exp < min_exp)
+ return false;
+
+ n /= pow10<T>(-exp);
}
else
{
n /= pow10<T>(-exp);
}
}
+ return true;
}
- inline void
+ inline bool
scale(int /*exp*/, unused_type /*n*/)
{
// no-op for unused_type
+ return true;
}
template <typename T>
- inline void
+ inline bool
scale(int exp, int frac, T& n)
{
- scale(exp - frac, n);
+ return scale(exp - frac, n);
}
- inline void
+ inline bool
scale(int /*exp*/, int /*frac*/, unused_type /*n*/)
{
// no-op for unused_type
+ return true;
}
inline float
@@ -150,6 +164,7 @@ namespace boost { namespace spirit { namespace x3
}
bool e_hit = false;
+ Iterator e_pos;
int frac_digits = 0;
// Try to parse the dot ('.' decimal point)
@@ -178,6 +193,7 @@ namespace boost { namespace spirit { namespace x3
}
// Now, let's see if we can parse the exponent prefix
+ e_pos = first;
e_hit = p.parse_exp(first, last);
}
else
@@ -191,6 +207,7 @@ namespace boost { namespace spirit { namespace x3
// If we must expect a dot and we didn't see an exponent
// prefix, return no-match.
+ e_pos = first;
e_hit = p.parse_exp(first, last);
if (p.expect_dot && !e_hit)
{
@@ -208,19 +225,25 @@ namespace boost { namespace spirit { namespace x3
{
// Got the exponent value. Scale the number by
// exp-frac_digits.
- extension::scale(exp, frac_digits, n);
+ if (!extension::scale(exp, frac_digits, n))
+ return false;
}
else
{
- // Oops, no exponent, return no-match.
- first = save;
- return false;
+ // If there is no number, disregard the exponent altogether.
+ // by resetting 'first' prior to the exponent prefix (e|E)
+ first = e_pos;
+
+ // Scale the number by -frac_digits.
+ if (!extension::scale(-frac_digits, n))
+ return false;
}
}
else if (frac_digits)
{
// No exponent found. Scale the number by -frac_digits.
- extension::scale(-frac_digits, n);
+ if (!extension::scale(-frac_digits, n))
+ return false;
}
// If we got a negative sign, negate the number
diff --git a/boost/spirit/home/x3/support/numeric_utils/pow10.hpp b/boost/spirit/home/x3/support/numeric_utils/pow10.hpp
index 1ff3a077a1..3a220d44d2 100644
--- a/boost/spirit/home/x3/support/numeric_utils/pow10.hpp
+++ b/boost/spirit/home/x3/support/numeric_utils/pow10.hpp
@@ -1,5 +1,5 @@
/*=============================================================================
- Copyright (c) 2001-2014 Joel de Guzman
+ Copyright (c) 2001-2019 Joel de Guzman
Copyright (c) 2001-2011 Hartmut Kaiser
http://spirit.sourceforge.net/
@@ -42,7 +42,11 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
}
};
-#if (DBL_MAX_10_EXP == 308) // for IEEE-754
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
+#pragma message("Spirit X3 requires full c++14 support.")
+#pragma message("Support for VS2015 will cease in the next Boost release.")
+#pragma message("This code branch will be removed.")
+
template <>
struct pow10_helper<double>
{
@@ -95,7 +99,46 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
return pow10_helper<double>::call(dim);
}
};
-#endif // for IEEE-754
+#else
+ template <typename T>
+ struct pow10_table
+ {
+ constexpr static std::size_t size =
+ std::numeric_limits<T>::max_exponent10;
+
+ constexpr pow10_table()
+ : exponents()
+ {
+ exponents[0] = T(1);
+ for (auto i = 1; i != size; ++i)
+ exponents[i] = exponents[i-1] * T(10);
+ }
+
+ T exponents[size];
+ };
+
+ template <typename T>
+ struct native_pow10_helper
+ {
+ static T call(unsigned dim)
+ {
+ constexpr auto table = pow10_table<T>();
+ return table.exponents[dim];
+ }
+ };
+
+ template <>
+ struct pow10_helper<float>
+ : native_pow10_helper<float> {};
+
+ template <>
+ struct pow10_helper<double>
+ : native_pow10_helper<double> {};
+
+ template <>
+ struct pow10_helper<long double>
+ : native_pow10_helper<long double> {};
+#endif
}
template <typename T>
diff --git a/boost/spirit/home/x3/support/traits/attribute_of.hpp b/boost/spirit/home/x3/support/traits/attribute_of.hpp
index 93ee79b57b..1a6d760035 100644
--- a/boost/spirit/home/x3/support/traits/attribute_of.hpp
+++ b/boost/spirit/home/x3/support/traits/attribute_of.hpp
@@ -16,8 +16,8 @@
namespace boost { namespace spirit { namespace x3 { namespace traits
{
///////////////////////////////////////////////////////////////////////////
- // Get the attribute type of a component. By default, this gets the
- // Component's attribute_type typedef or instantiates a nested attribute
+ // Get the attribute type of a component. By default, this gets the
+ // Component's attribute_type typedef or instantiates a nested attribute
// metafunction. Components may specialize this if such an attribute_type
// is not readily available (e.g. expensive to compute at compile time).
///////////////////////////////////////////////////////////////////////////
@@ -28,28 +28,27 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
{
template <typename Component, typename Context, typename Enable = void>
struct default_attribute_of;
-
+
template <typename Component, typename Context>
- struct default_attribute_of<Component, Context,
+ struct default_attribute_of<Component, Context,
typename disable_if_substitution_failure<
typename Component::attribute_type>::type>
: mpl::identity<typename Component::attribute_type> {};
-
+
template <typename Component, typename Context>
- struct default_attribute_of<Component, Context,
+ struct default_attribute_of<Component, Context,
typename disable_if_substitution_failure<
typename Component::template attribute<Context>::type>::type>
: Component::template attribute<Context> {};
-
+
template <typename Component, typename Context>
struct default_attribute_of<Component, Context,
typename enable_if_c<Component::is_pass_through_unary>::type>
: attribute_of<typename Component::subject_type, Context>{};
}
-
+
template <typename Component, typename Context, typename Enable>
struct attribute_of : detail::default_attribute_of<Component, Context> {};
-
}}}}
#endif
diff --git a/boost/spirit/home/x3/support/traits/pseudo_attribute.hpp b/boost/spirit/home/x3/support/traits/pseudo_attribute.hpp
new file mode 100644
index 0000000000..4bfae46736
--- /dev/null
+++ b/boost/spirit/home/x3/support/traits/pseudo_attribute.hpp
@@ -0,0 +1,34 @@
+/*=============================================================================
+ Copyright (c) 2019 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_X3_PSEUDO_ATTRIBUTE_OF_MAY_15_2019_1012PM)
+#define BOOST_SPIRIT_X3_PSEUDO_ATTRIBUTE_OF_MAY_15_2019_1012PM
+
+#include <utility>
+
+namespace boost { namespace spirit { namespace x3 { namespace traits
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Pseudo attributes are placeholders for parsers that can only know
+ // its actual attribute at parse time. This trait customization point
+ // provides a mechanism to convert the trait to the actual trait at
+ // parse time.
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Context, typename Attribute, typename Iterator
+ , typename Enable = void>
+ struct pseudo_attribute
+ {
+ using attribute_type = Attribute;
+ using type = Attribute;
+
+ static type&& call(Iterator&, Iterator const&, attribute_type&& attr)
+ {
+ return std::forward<type>(attr);
+ }
+ };
+}}}}
+
+#endif
diff --git a/boost/spirit/home/x3/support/traits/string_traits.hpp b/boost/spirit/home/x3/support/traits/string_traits.hpp
index 44c8d144a8..acbc4346cf 100644
--- a/boost/spirit/home/x3/support/traits/string_traits.hpp
+++ b/boost/spirit/home/x3/support/traits/string_traits.hpp
@@ -11,129 +11,10 @@
#include <string>
#include <boost/mpl/bool.hpp>
-#include <boost/mpl/identity.hpp>
namespace boost { namespace spirit { namespace x3 { namespace traits
{
///////////////////////////////////////////////////////////////////////////
- // Determine if T is a character type
- ///////////////////////////////////////////////////////////////////////////
- template <typename T>
- struct is_char : mpl::false_ {};
-
- template <typename T>
- struct is_char<T const> : is_char<T> {};
-
- template <>
- struct is_char<char> : mpl::true_ {};
-
- template <>
- struct is_char<wchar_t> : mpl::true_ {};
-
- ///////////////////////////////////////////////////////////////////////////
- // Determine if T is a string
- ///////////////////////////////////////////////////////////////////////////
- template <typename T>
- struct is_string : mpl::false_ {};
-
- template <typename T>
- struct is_string<T const> : is_string<T> {};
-
- template <>
- struct is_string<char const*> : mpl::true_ {};
-
- template <>
- struct is_string<wchar_t const*> : mpl::true_ {};
-
- template <>
- struct is_string<char*> : mpl::true_ {};
-
- template <>
- struct is_string<wchar_t*> : mpl::true_ {};
-
- template <std::size_t N>
- struct is_string<char[N]> : mpl::true_ {};
-
- template <std::size_t N>
- struct is_string<wchar_t[N]> : mpl::true_ {};
-
- template <std::size_t N>
- struct is_string<char const[N]> : mpl::true_ {};
-
- template <std::size_t N>
- struct is_string<wchar_t const[N]> : mpl::true_ {};
-
- template <std::size_t N>
- struct is_string<char(&)[N]> : mpl::true_ {};
-
- template <std::size_t N>
- struct is_string<wchar_t(&)[N]> : mpl::true_ {};
-
- template <std::size_t N>
- struct is_string<char const(&)[N]> : mpl::true_ {};
-
- template <std::size_t N>
- struct is_string<wchar_t const(&)[N]> : mpl::true_ {};
-
- template <typename T, typename Traits, typename Allocator>
- struct is_string<std::basic_string<T, Traits, Allocator> > : mpl::true_ {};
-
- ///////////////////////////////////////////////////////////////////////////
- // Get the underlying char type of a string
- ///////////////////////////////////////////////////////////////////////////
- template <typename T>
- struct char_type_of;
-
- template <typename T>
- struct char_type_of<T const> : char_type_of<T> {};
-
- template <>
- struct char_type_of<char> : mpl::identity<char> {};
-
- template <>
- struct char_type_of<wchar_t> : mpl::identity<wchar_t> {};
-
- template <>
- struct char_type_of<char const*> : mpl::identity<char const> {};
-
- template <>
- struct char_type_of<wchar_t const*> : mpl::identity<wchar_t const> {};
-
- template <>
- struct char_type_of<char*> : mpl::identity<char> {};
-
- template <>
- struct char_type_of<wchar_t*> : mpl::identity<wchar_t> {};
-
- template <std::size_t N>
- struct char_type_of<char[N]> : mpl::identity<char> {};
-
- template <std::size_t N>
- struct char_type_of<wchar_t[N]> : mpl::identity<wchar_t> {};
-
- template <std::size_t N>
- struct char_type_of<char const[N]> : mpl::identity<char const> {};
-
- template <std::size_t N>
- struct char_type_of<wchar_t const[N]> : mpl::identity<wchar_t const> {};
-
- template <std::size_t N>
- struct char_type_of<char(&)[N]> : mpl::identity<char> {};
-
- template <std::size_t N>
- struct char_type_of<wchar_t(&)[N]> : mpl::identity<wchar_t> {};
-
- template <std::size_t N>
- struct char_type_of<char const(&)[N]> : mpl::identity<char const> {};
-
- template <std::size_t N>
- struct char_type_of<wchar_t const(&)[N]> : mpl::identity<wchar_t const> {};
-
- template <typename T, typename Traits, typename Allocator>
- struct char_type_of<std::basic_string<T, Traits, Allocator> >
- : mpl::identity<T> {};
-
- ///////////////////////////////////////////////////////////////////////////
// Get the C string from a string
///////////////////////////////////////////////////////////////////////////
template <typename String>
@@ -142,8 +23,6 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
template <typename String>
struct extract_c_string
{
- typedef typename char_type_of<String>::type char_type;
-
template <typename T>
static T const* call (T* str)
{
@@ -161,9 +40,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
template <typename T>
struct extract_c_string<T const>
{
- typedef typename extract_c_string<T>::char_type char_type;
-
- static typename extract_c_string<T>::char_type const* call (T const str)
+ static decltype(auto) call(T const str)
{
return extract_c_string<T>::call(str);
}
@@ -173,9 +50,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
template <typename T>
struct extract_c_string<T&>
{
- typedef typename extract_c_string<T>::char_type char_type;
-
- static typename extract_c_string<T>::char_type const* call (T& str)
+ static decltype(auto) call(T& str)
{
return extract_c_string<T>::call(str);
}
@@ -185,9 +60,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
template <typename T>
struct extract_c_string<T const&>
{
- typedef typename extract_c_string<T>::char_type char_type;
-
- static typename extract_c_string<T>::char_type const* call (T const& str)
+ static decltype(auto) call(T const& str)
{
return extract_c_string<T>::call(str);
}
@@ -196,8 +69,6 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
template <typename T, typename Traits, typename Allocator>
struct extract_c_string<std::basic_string<T, Traits, Allocator> >
{
- typedef T char_type;
-
typedef std::basic_string<T, Traits, Allocator> string;
static T const* call (string const& str)
@@ -207,29 +78,25 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
};
template <typename T>
- typename extract_c_string<T*>::char_type const*
- get_c_string(T* str)
+ decltype(auto) get_c_string(T* str)
{
return extract_c_string<T*>::call(str);
}
template <typename T>
- typename extract_c_string<T const*>::char_type const*
- get_c_string(T const* str)
+ decltype(auto) get_c_string(T const* str)
{
return extract_c_string<T const*>::call(str);
}
template <typename String>
- typename extract_c_string<String>::char_type const*
- get_c_string(String& str)
+ decltype(auto) get_c_string(String& str)
{
return extract_c_string<String>::call(str);
}
template <typename String>
- typename extract_c_string<String>::char_type const*
- get_c_string(String const& str)
+ decltype(auto) get_c_string(String const& str)
{
return extract_c_string<String>::call(str);
}
diff --git a/boost/spirit/home/x3/support/unused.hpp b/boost/spirit/home/x3/support/unused.hpp
index 0486df3090..91471307a6 100644
--- a/boost/spirit/home/x3/support/unused.hpp
+++ b/boost/spirit/home/x3/support/unused.hpp
@@ -10,19 +10,12 @@
#include <iosfwd>
-#if defined(BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable: 4522) // multiple assignment operators specified warning
-#endif
-
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace x3
{
struct unused_type
{
- unused_type()
- {
- }
+ unused_type() = default;
template <typename T>
unused_type(T const&)
@@ -43,18 +36,6 @@ namespace boost { namespace spirit { namespace x3
return *this;
}
- unused_type const&
- operator=(unused_type const&) const
- {
- return *this;
- }
-
- unused_type&
- operator=(unused_type const&)
- {
- return *this;
- }
-
// unused_type can also masquerade as an empty context (see context.hpp)
template <typename ID>
@@ -77,8 +58,4 @@ namespace boost { namespace spirit { namespace x3
}
}}}
-#if defined(BOOST_MSVC)
-# pragma warning(pop)
-#endif
-
#endif
diff --git a/boost/spirit/home/x3/support/utility/testing.hpp b/boost/spirit/home/x3/support/utility/testing.hpp
deleted file mode 100644
index eb99f69204..0000000000
--- a/boost/spirit/home/x3/support/utility/testing.hpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/*=============================================================================
- Copyright (c) 2001-2015 Joel de Guzman
-
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-=============================================================================*/
-#if !defined(BOOST_SPIRIT_X3_TEST_UTILITIES)
-#define BOOST_SPIRIT_X3_TEST_UTILITIES
-
-#include <boost/regex.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/filesystem/fstream.hpp>
-
-namespace boost { namespace spirit { namespace x3 { namespace testing
-{
- namespace fs = boost::filesystem;
-
- ////////////////////////////////////////////////////////////////////////////
- // compare
- //
- // Compares the contents of in with the template tem. The template
- // may include embedded regular expressions marked up within re_prefix
- // and re_suffix tags. For example, given the default RE markup, this
- // template <%[0-9]+%> will match any integer in in. The function
- // will return the first non-matching position. The flag full_match
- // indicates a full match. It is possible for returned pos to be
- // at the end of in (in.end()) while still returning full_match ==
- // false. In that case, we have a partial match.
- ////////////////////////////////////////////////////////////////////////////
-
- template <typename Iterator>
- struct compare_result
- {
- compare_result(
- Iterator pos
- , bool full_match
- ) : pos(pos), full_match(full_match) {}
-
- Iterator pos;
- bool full_match;
- };
-
- template <typename Range>
- compare_result<typename Range::const_iterator>
- compare(
- Range const& in
- , Range const& tem
- , char const* re_prefix = "<%"
- , char const* re_suffix = "%>"
- );
-
- ////////////////////////////////////////////////////////////////////////////
- // compare
- //
- // 1) Call f, given the contents of input_path loaded in a string.
- // The result of calling f is the output string.
- // 2) Compare the result of calling f with expected template
- // file (expect_path) using the low-level compare utility
- // abive
- ////////////////////////////////////////////////////////////////////////////
- template <typename F>
- bool compare(
- fs::path input_path, fs::path expect_path
- , F f
- , char const* re_prefix = "<%"
- , char const* re_suffix = "%>"
- );
-
- ////////////////////////////////////////////////////////////////////////////
- // for_each_file
- //
- // For each *.input and *.expect file in a given directory,
- // call the function f, passing in the *.input and *.expect paths.
- ////////////////////////////////////////////////////////////////////////////
- template <typename F>
- int for_each_file(fs::path p, F f);
-
- ////////////////////////////////////////////////////////////////////////////
- // load_file
- //
- // Load file into a string.
- ////////////////////////////////////////////////////////////////////////////
- std::string load(fs::path p);
-
- ////////////////////////////////////////////////////////////////////////////
- // Implementation
- ////////////////////////////////////////////////////////////////////////////
-
- template <typename Iterator>
- inline bool is_regex(
- Iterator& first
- , Iterator last
- , std::string& re
- , char const* re_prefix
- , char const* re_suffix
- )
- {
- boost::regex e(re_prefix + std::string("(.*?)") + re_suffix);
- boost::match_results<Iterator> what;
- if (boost::regex_search(
- first, last, what, e
- , boost::match_default | boost::match_continuous))
- {
- re = what[1].str();
- first = what[0].second;
- return true;
- }
- return false;
- }
-
- template <typename Range>
- inline compare_result<typename Range::const_iterator>
- compare(
- Range const& in
- , Range const& tem
- , char const* re_prefix
- , char const* re_suffix
- )
- {
- typedef typename Range::const_iterator iter_t;
- typedef compare_result<iter_t> compare_result_t;
-
- iter_t in_first = in.begin();
- iter_t in_last = in.end();
- iter_t tem_first = tem.begin();
- iter_t tem_last = tem.end();
- std::string re;
-
- while (in_first != in_last && tem_first != tem_last)
- {
- if (is_regex(tem_first, tem_last, re, re_prefix, re_suffix))
- {
- boost::match_results<iter_t> what;
- boost::regex e(re);
- if (!boost::regex_search(
- in_first, in_last, what, e
- , boost::match_default | boost::match_continuous))
- {
- // RE mismatch: exit now.
- return compare_result_t(in_first, false);
- }
- else
- {
- // RE match: gobble the matching string.
- in_first = what[0].second;
- }
- }
- else
- {
- // Char by char comparison. Exit if we have a mismatch.
- if (*in_first++ != *tem_first++)
- return compare_result_t(in_first, false);
- }
- }
-
- // Ignore trailing spaces in template
- bool has_trailing_nonspaces = false;
- while (tem_first != tem_last)
- {
- if (!std::isspace(*tem_first++))
- {
- has_trailing_nonspaces = true;
- break;
- }
- }
- while (in_first != in_last)
- {
- if (!std::isspace(*in_first++))
- {
- has_trailing_nonspaces = true;
- break;
- }
- }
- // return a full match only if the template is fully matched and if there
- // are no more characters to match in the source
- return compare_result_t(in_first, !has_trailing_nonspaces);
- }
-
- template <typename F>
- inline int for_each_file(fs::path p, F f)
- {
- try
- {
- if (fs::exists(p) && fs::is_directory(p))
- {
- for (auto i = fs::directory_iterator(p); i != fs::directory_iterator(); ++i)
- {
- auto ext = fs::extension(i->path());
- if (ext == ".input")
- {
- auto input_path = i->path();
- auto expect_path = input_path;
- expect_path.replace_extension(".expect");
- f(input_path, expect_path);
- }
- }
- }
- else
- {
- std::cerr << "Directory: " << fs::absolute(p) << " does not exist." << std::endl;
- return 1;
- }
- }
-
- catch (const fs::filesystem_error& ex)
- {
- std::cerr << ex.what() << '\n';
- return 1;
- }
- return 0;
- }
-
- inline std::string load(fs::path p)
- {
- boost::filesystem::ifstream file(p);
- if (!file)
- return "";
- std::string contents((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
- return contents;
- }
-
- template <typename F>
- inline bool compare(
- fs::path input_path, fs::path expect_path
- , F f
- , char const* re_prefix
- , char const* re_suffix
- )
- {
- std::string output = f(load(input_path), input_path);
- std::string expected = load(expect_path);
-
- auto result = compare(output, expected, re_prefix, re_suffix);
- if (!result.full_match)
- {
- std::cout << "=============================================" << std::endl;
- std::cout << "==== Mismatch Found:" << std::endl;
- int line = 1;
- int col = 1;
- for (auto i = output.begin(); i != result.pos; ++i)
- {
- if (*i == '\n')
- {
- line++;
- col = 0;
- }
- ++col;
- }
-
- std::cerr
- << "==== File: " << expect_path
- << ", Line: " << line
- << ", Column: " << col
- << std::endl;
- std::cerr << "=============================================" << std::endl;
-
- // Print output
- std::cerr << output;
- std::cerr << "=============================================" << std::endl;
- std::cerr << "==== End" << std::endl;
- std::cerr << "=============================================" << std::endl;
- return false;
- }
- return true;
- }
-
-}}}}
-
-#endif
diff --git a/boost/spirit/repository/home/qi/directive/kwd.hpp b/boost/spirit/repository/home/qi/directive/kwd.hpp
index e7338df432..684541d7e7 100644
--- a/boost/spirit/repository/home/qi/directive/kwd.hpp
+++ b/boost/spirit/repository/home/qi/directive/kwd.hpp
@@ -172,9 +172,8 @@ template <typename T>
}
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- kwd_pass_iterator& operator= (kwd_pass_iterator const&);
+ BOOST_DELETED_FUNCTION(kwd_pass_iterator& operator= (kwd_pass_iterator const&))
};
template <typename T>
@@ -203,9 +202,8 @@ template <typename T>
}
T const exact;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- kwd_exact_iterator& operator= (kwd_exact_iterator const&);
+ BOOST_DELETED_FUNCTION(kwd_exact_iterator& operator= (kwd_exact_iterator const&))
};
template <typename T>
@@ -235,9 +233,8 @@ template <typename T>
T const min;
T const max;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- kwd_finite_iterator& operator= (kwd_finite_iterator const&);
+ BOOST_DELETED_FUNCTION(kwd_finite_iterator& operator= (kwd_finite_iterator const&))
};
template <typename T>
@@ -255,9 +252,8 @@ template <typename T>
}
T const min;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- kwd_infinite_iterator& operator= (kwd_infinite_iterator const&);
+ BOOST_DELETED_FUNCTION(kwd_infinite_iterator& operator= (kwd_infinite_iterator const&))
};
// This class enables the transportation of parameters needed to call
@@ -439,11 +435,12 @@ template <typename T>
no_case_keyword,
spirit::qi::no_case_literal_string< KeywordType, true>,
spirit::qi::literal_string<KeywordType, true> >::type keyword_string_type;
- keyword_string_type keyword;
- private:
+ keyword_string_type keyword;
+
// silence MSVC warning C4512: assignment operator could not be generated
- kwd_parser& operator= (kwd_parser const&);
+ BOOST_DELETED_FUNCTION(kwd_parser& operator= (kwd_parser const&))
+ private:
template <typename Iterator, typename Context, typename Skipper>
static spirit::qi::detail::fail_function<Iterator, Context, Skipper>
fail_function(
@@ -585,10 +582,11 @@ template <typename Subject, typename KeywordType, typename LoopIter, typename Di
LoopIter iter;
KeywordType keyword;
- private:
+
// silence MSVC warning C4512: assignment operator could not be generated
- complex_kwd_parser& operator= (complex_kwd_parser const&);
+ BOOST_DELETED_FUNCTION(complex_kwd_parser& operator= (complex_kwd_parser const&))
+ private:
template <typename Iterator, typename Context, typename Skipper>
static spirit::qi::detail::fail_function<Iterator, Context, Skipper>
fail_function(
diff --git a/boost/spirit/repository/home/qi/operator/detail/keywords.hpp b/boost/spirit/repository/home/qi/operator/detail/keywords.hpp
index f672df737f..c8bd0a0b26 100644
--- a/boost/spirit/repository/home/qi/operator/detail/keywords.hpp
+++ b/boost/spirit/repository/home/qi/operator/detail/keywords.hpp
@@ -689,9 +689,8 @@ namespace boost { namespace spirit { namespace repository { namespace qi { names
Skipper const& skipper;
ParseDispatcher const& dispatcher;
- private:
// silence MSVC warning C4512: assignment operator could not be generated
- complex_kwd_function& operator= (complex_kwd_function const&);
+ BOOST_DELETED_FUNCTION(complex_kwd_function& operator= (complex_kwd_function const&))
};
diff --git a/boost/stacktrace/detail/frame_msvc.ipp b/boost/stacktrace/detail/frame_msvc.ipp
index 3159129903..21f6f90a7c 100644
--- a/boost/stacktrace/detail/frame_msvc.ipp
+++ b/boost/stacktrace/detail/frame_msvc.ipp
@@ -98,7 +98,7 @@ public:
};
-static std::string mingw_demangling_workaround(const std::string& s) {
+inline std::string mingw_demangling_workaround(const std::string& s) {
#ifdef BOOST_GCC
if (s.empty()) {
return s;
@@ -114,6 +114,12 @@ static std::string mingw_demangling_workaround(const std::string& s) {
#endif
}
+inline void trim_right_zeroes(std::string& s) {
+ while (s.back() == '\0') {
+ s.pop_back();
+ }
+}
+
class debugging_symbols: boost::noncopyable {
static void try_init_com(com_holder< ::IDebugSymbols>& idebug, const com_global_initer& com) BOOST_NOEXCEPT {
com_holder< ::IDebugClient> iclient(com);
@@ -217,6 +223,7 @@ public:
&size,
0
));
+ trim_right_zeroes(result);
} else if (res) {
result = name;
}
@@ -301,6 +308,7 @@ public:
&size,
0
));
+ trim_right_zeroes(result.first);
result.second = line_num;
if (!res) {
diff --git a/boost/stacktrace/detail/frame_unwind.ipp b/boost/stacktrace/detail/frame_unwind.ipp
index a3e99ac20b..5b7cfa7e71 100644
--- a/boost/stacktrace/detail/frame_unwind.ipp
+++ b/boost/stacktrace/detail/frame_unwind.ipp
@@ -59,6 +59,9 @@ public:
std::string to_string(const frame* frames, std::size_t size) {
std::string res;
+ if (size == 0) {
+ return res;
+ }
res.reserve(64 * size);
to_string_impl impl;
@@ -82,6 +85,10 @@ std::string to_string(const frame* frames, std::size_t size) {
std::string frame::name() const {
+ if (!addr_) {
+ return std::string();
+ }
+
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
::Dl_info dli;
const bool dl_ok = !!::dladdr(const_cast<void*>(addr_), &dli); // `dladdr` on Solaris accepts nonconst addresses
@@ -93,6 +100,10 @@ std::string frame::name() const {
}
std::string to_string(const frame& f) {
+ if (!f) {
+ return std::string();
+ }
+
boost::stacktrace::detail::to_string_impl impl;
return impl(f.address());
}
diff --git a/boost/stacktrace/detail/libbacktrace_impls.hpp b/boost/stacktrace/detail/libbacktrace_impls.hpp
index 52701ecbe1..753234a545 100644
--- a/boost/stacktrace/detail/libbacktrace_impls.hpp
+++ b/boost/stacktrace/detail/libbacktrace_impls.hpp
@@ -195,6 +195,10 @@ inline std::string name_impl(const void* addr) {
std::string frame::source_file() const {
std::string res;
+ if (!addr_) {
+ return res;
+ }
+
boost::stacktrace::detail::program_location prog_location;
::backtrace_state* state = boost::stacktrace::detail::construct_state(prog_location);
@@ -213,6 +217,10 @@ std::string frame::source_file() const {
}
std::size_t frame::source_line() const {
+ if (!addr_) {
+ return 0;
+ }
+
boost::stacktrace::detail::program_location prog_location;
::backtrace_state* state = boost::stacktrace::detail::construct_state(prog_location);
diff --git a/boost/system/detail/config.hpp b/boost/system/detail/config.hpp
index 2ad8201476..5742a94d14 100644
--- a/boost/system/detail/config.hpp
+++ b/boost/system/detail/config.hpp
@@ -22,6 +22,11 @@
# undef BOOST_SYSTEM_HAS_SYSTEM_ERROR
#endif
+#if defined(BOOST_NO_CXX11_HDR_MUTEX)
+// Required for thread-safe map manipulation
+# undef BOOST_SYSTEM_HAS_SYSTEM_ERROR
+#endif
+
// BOOST_SYSTEM_NOEXCEPT
// Retained for backward compatibility
@@ -43,15 +48,4 @@
# define BOOST_SYSTEM_CONSTEXPR
#endif
-// BOOST_SYSTEM_REQUIRE_CONST_INIT
-
-#define BOOST_SYSTEM_REQUIRE_CONST_INIT
-
-#if defined(__has_cpp_attribute)
-#if __has_cpp_attribute(clang::require_constant_initialization)
-# undef BOOST_SYSTEM_REQUIRE_CONST_INIT
-# define BOOST_SYSTEM_REQUIRE_CONST_INIT [[clang::require_constant_initialization]]
-#endif
-#endif
-
#endif // BOOST_SYSTEM_DETAIL_CONFIG_HPP_INCLUDED
diff --git a/boost/system/detail/std_interoperability.hpp b/boost/system/detail/std_interoperability.hpp
index b1b41d39b4..a6ec728ef7 100644
--- a/boost/system/detail/std_interoperability.hpp
+++ b/boost/system/detail/std_interoperability.hpp
@@ -10,6 +10,7 @@
#include <system_error>
#include <map>
#include <memory>
+#include <mutex>
//
@@ -30,8 +31,20 @@ private:
public:
- explicit std_category( boost::system::error_category const * pc ): pc_( pc )
+ explicit std_category( boost::system::error_category const * pc, unsigned id ): pc_( pc )
{
+ if( id != 0 )
+ {
+#if defined(_MSC_VER) && defined(_CPPLIB_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000
+
+ // Poking into the protected _Addr member of std::error_category
+ // is not a particularly good programming practice, but what can
+ // you do
+
+ _Addr = id;
+
+#endif
+ }
}
virtual const char * name() const BOOST_NOEXCEPT
@@ -53,24 +66,50 @@ public:
virtual bool equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT;
};
+inline std::error_category const & to_std_category( boost::system::error_category const & cat ) BOOST_SYMBOL_VISIBLE;
+
+struct cat_ptr_less
+{
+ bool operator()( boost::system::error_category const * p1, boost::system::error_category const * p2 ) const BOOST_NOEXCEPT
+ {
+ return *p1 < *p2;
+ }
+};
+
inline std::error_category const & to_std_category( boost::system::error_category const & cat )
{
- typedef std::map< boost::system::error_category const *, std::unique_ptr<std_category> > map_type;
+ if( cat == boost::system::system_category() )
+ {
+ static const std_category system_instance( &cat, 0x1F4D7 );
+ return system_instance;
+ }
+ else if( cat == boost::system::generic_category() )
+ {
+ static const std_category generic_instance( &cat, 0x1F4D3 );
+ return generic_instance;
+ }
+ else
+ {
+ typedef std::map< boost::system::error_category const *, std::unique_ptr<std_category>, cat_ptr_less > map_type;
- static map_type map_;
+ static map_type map_;
+ static std::mutex map_mx_;
- map_type::iterator i = map_.find( &cat );
+ std::lock_guard<std::mutex> guard( map_mx_ );
- if( i == map_.end() )
- {
- std::unique_ptr<std_category> p( new std_category( &cat ) );
+ map_type::iterator i = map_.find( &cat );
- std::pair<map_type::iterator, bool> r = map_.insert( map_type::value_type( &cat, std::move( p ) ) );
+ if( i == map_.end() )
+ {
+ std::unique_ptr<std_category> p( new std_category( &cat, 0 ) );
- i = r.first;
- }
+ std::pair<map_type::iterator, bool> r = map_.insert( map_type::value_type( &cat, std::move( p ) ) );
- return *i->second;
+ i = r.first;
+ }
+
+ return *i->second;
+ }
}
inline bool std_category::equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT
diff --git a/boost/system/detail/system_category_win32.hpp b/boost/system/detail/system_category_win32.hpp
index a46c8b2e22..da256e1d70 100644
--- a/boost/system/detail/system_category_win32.hpp
+++ b/boost/system/detail/system_category_win32.hpp
@@ -264,6 +264,7 @@ inline error_condition system_category_default_error_condition_win32( int ev ) B
case ERROR_CANTOPEN_: return make_error_condition( io_error );
case ERROR_CANTREAD_: return make_error_condition( io_error );
case ERROR_CANTWRITE_: return make_error_condition( io_error );
+ case ERROR_CONNECTION_ABORTED_: return make_error_condition( connection_aborted );
case ERROR_CURRENT_DIRECTORY_: return make_error_condition( permission_denied );
case ERROR_DEV_NOT_EXIST_: return make_error_condition( no_such_device );
case ERROR_DEVICE_IN_USE_: return make_error_condition( device_or_resource_busy );
diff --git a/boost/system/error_code.hpp b/boost/system/error_code.hpp
index f1d7ddb745..f0a151e87b 100644
--- a/boost/system/error_code.hpp
+++ b/boost/system/error_code.hpp
@@ -329,14 +329,14 @@ public:
namespace detail
{
-template<class T> struct cat_holder
+template<class T> struct BOOST_SYMBOL_VISIBLE cat_holder
{
- BOOST_SYSTEM_REQUIRE_CONST_INIT static constexpr system_error_category system_category_instance{};
- BOOST_SYSTEM_REQUIRE_CONST_INIT static constexpr generic_error_category generic_category_instance{};
+ static constexpr system_error_category system_category_instance{};
+ static constexpr generic_error_category generic_category_instance{};
};
-template<class T> BOOST_SYSTEM_REQUIRE_CONST_INIT constexpr system_error_category cat_holder<T>::system_category_instance;
-template<class T> BOOST_SYSTEM_REQUIRE_CONST_INIT constexpr generic_error_category cat_holder<T>::generic_category_instance;
+template<class T> constexpr system_error_category cat_holder<T>::system_category_instance;
+template<class T> constexpr generic_error_category cat_holder<T>::generic_category_instance;
} // namespace detail
@@ -352,12 +352,16 @@ constexpr error_category const & generic_category() BOOST_NOEXCEPT
#else // #if defined(BOOST_SYSTEM_HAS_CONSTEXPR)
+inline error_category const & system_category() BOOST_NOEXCEPT BOOST_SYMBOL_VISIBLE;
+
inline error_category const & system_category() BOOST_NOEXCEPT
{
static const detail::system_error_category system_category_instance;
return system_category_instance;
}
+inline error_category const & generic_category() BOOST_NOEXCEPT BOOST_SYMBOL_VISIBLE;
+
inline error_category const & generic_category() BOOST_NOEXCEPT
{
static const detail::generic_error_category generic_category_instance;
@@ -780,7 +784,7 @@ inline std::size_t hash_value( error_code const & ec )
if( id == 0 )
{
- id = reinterpret_cast<boost::ulong_long_type>( &cat );
+ id = reinterpret_cast<boost::uintptr_t>( &cat );
}
boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325;
diff --git a/boost/test/auto_unit_test.hpp b/boost/test/auto_unit_test.hpp
index 99acd162ab..71ae170a60 100644
--- a/boost/test/auto_unit_test.hpp
+++ b/boost/test/auto_unit_test.hpp
@@ -13,6 +13,9 @@
#ifndef BOOST_TEST_AUTO_UNIT_TEST_HPP_071894GER
#define BOOST_TEST_AUTO_UNIT_TEST_HPP_071894GER
+#include <boost/config/header_deprecated.hpp>
+BOOST_HEADER_DEPRECATED( "This header is deprecated. Please use <boost/test/unit_test.hpp> instead." )
+
#include <boost/test/unit_test.hpp>
#endif // BOOST_TEST_AUTO_UNIT_TEST_HPP_071894GER
diff --git a/boost/test/floating_point_comparison.hpp b/boost/test/floating_point_comparison.hpp
index e889274477..9410475fc6 100644
--- a/boost/test/floating_point_comparison.hpp
+++ b/boost/test/floating_point_comparison.hpp
@@ -10,5 +10,9 @@
//! @deprecated Use boost/test/tools/floating_point_comparison.hpp instead
// ***************************************************************************
+#include <boost/config/header_deprecated.hpp>
+BOOST_HEADER_DEPRECATED( "This header is deprecated. Please use <boost/test/tools/floating_point_comparison.hpp> instead." )
+
+
// Boost.Test
#include <boost/test/tools/floating_point_comparison.hpp>
diff --git a/boost/test/framework.hpp b/boost/test/framework.hpp
index dd0756f9d4..1a139e099c 100644
--- a/boost/test/framework.hpp
+++ b/boost/test/framework.hpp
@@ -262,6 +262,12 @@ namespace impl {
// exclusively for self test
BOOST_TEST_DECL void setup_for_execution( test_unit const& );
BOOST_TEST_DECL void setup_loggers( );
+
+// Helper for setting the name of the master test suite globally
+struct BOOST_TEST_DECL master_test_suite_name_setter {
+ master_test_suite_name_setter( const_string name );
+};
+
} // namespace impl
// ************************************************************************** //
diff --git a/boost/test/impl/decorator.ipp b/boost/test/impl/decorator.ipp
index ac6cc7e278..3a0ebb7061 100644
--- a/boost/test/impl/decorator.ipp
+++ b/boost/test/impl/decorator.ipp
@@ -111,7 +111,7 @@ stack_decorator::operator*() const
}
void
-stack_decorator::apply( test_unit& tu )
+stack_decorator::apply( test_unit& /*tu*/ )
{
// does nothing by definition
}
diff --git a/boost/test/impl/execution_monitor.ipp b/boost/test/impl/execution_monitor.ipp
index 2c2cd3871f..ccc449728f 100644
--- a/boost/test/impl/execution_monitor.ipp
+++ b/boost/test/impl/execution_monitor.ipp
@@ -1167,7 +1167,7 @@ execution_monitor::catch_signals( boost::function<int ()> const& F )
htimer = ::CreateWaitableTimer(
NULL,
TRUE,
- TEXT("Boost.Test timer"));
+ NULL); // naming the timer might create collisions
if( htimer != INVALID_HANDLE_VALUE ) {
LARGE_INTEGER liDueTime;
diff --git a/boost/test/impl/framework.ipp b/boost/test/impl/framework.ipp
index c35469eeb3..44c7c31660 100644
--- a/boost/test/impl/framework.ipp
+++ b/boost/test/impl/framework.ipp
@@ -1525,6 +1525,14 @@ master_test_suite()
return *impl::s_frk_state().m_master_test_suite;
}
+namespace impl {
+
+master_test_suite_name_setter::master_test_suite_name_setter(const_string name) {
+ assign_op( master_test_suite().p_name.value, name.trim( "\"" ), 0 );
+}
+
+}
+
//____________________________________________________________________________//
// ************************************************************************** //
diff --git a/boost/test/included/unit_test_framework.hpp b/boost/test/included/unit_test_framework.hpp
index 5bf366ad80..1203311698 100644
--- a/boost/test/included/unit_test_framework.hpp
+++ b/boost/test/included/unit_test_framework.hpp
@@ -9,4 +9,8 @@
/// @deprecated
// ***************************************************************************
+#include <boost/config/header_deprecated.hpp>
+BOOST_HEADER_DEPRECATED( "This header is deprecated. Please use <boost/test/included/unit_test.hpp> instead." )
+
+
#include <boost/test/included/unit_test.hpp>
diff --git a/boost/test/output_test_stream.hpp b/boost/test/output_test_stream.hpp
index 26eaf320ac..bbce1030f0 100644
--- a/boost/test/output_test_stream.hpp
+++ b/boost/test/output_test_stream.hpp
@@ -10,5 +10,9 @@
//!@deprecated Use boost/test/tools/output_test_stream.hpp instead
// ***************************************************************************
+#include <boost/config/header_deprecated.hpp>
+BOOST_HEADER_DEPRECATED( "This header is deprecated. Please use <boost/test/tools/output_test_stream.hpp> instead." )
+
+
// Boost.Test
#include <boost/test/tools/output_test_stream.hpp>
diff --git a/boost/test/predicate_result.hpp b/boost/test/predicate_result.hpp
index 9b57363713..cf69590370 100644
--- a/boost/test/predicate_result.hpp
+++ b/boost/test/predicate_result.hpp
@@ -10,5 +10,9 @@
/// @deprecated Use boost/test/tools/assertion_result.hpp instead
// ***************************************************************************
+#include <boost/config/header_deprecated.hpp>
+BOOST_HEADER_DEPRECATED( "This header is deprecated. Please use <boost/test/tools/assertion_result.hpp> instead." )
+
+
// Boost.Test
#include <boost/test/tools/assertion_result.hpp>
diff --git a/boost/test/test_case_template.hpp b/boost/test/test_case_template.hpp
index c01bd0738a..4f4ad83cb1 100644
--- a/boost/test/test_case_template.hpp
+++ b/boost/test/test_case_template.hpp
@@ -10,4 +10,8 @@
/// @deprecated Use @c boost/test/unit_test.hpp instead
// ***************************************************************************
+#include <boost/config/header_deprecated.hpp>
+BOOST_HEADER_DEPRECATED( "This header is deprecated. Please use <boost/test/unit_test.hpp> instead." )
+
+
#include <boost/test/unit_test.hpp>
diff --git a/boost/test/tools/floating_point_comparison.hpp b/boost/test/tools/floating_point_comparison.hpp
index 810840e345..114358412f 100644
--- a/boost/test/tools/floating_point_comparison.hpp
+++ b/boost/test/tools/floating_point_comparison.hpp
@@ -23,6 +23,8 @@
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/type_traits/is_array.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_void.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/utility/enable_if.hpp>
@@ -50,6 +52,23 @@ struct tolerance_based_delegate;
template <typename T>
struct tolerance_based_delegate<T, false> : mpl::false_ {};
+// from https://stackoverflow.com/a/16509511/1617295
+template<typename T>
+class is_abstract_class_or_function
+{
+ typedef char (&Two)[2];
+ template<typename U> static char test(U(*)[1]);
+ template<typename U> static Two test(...);
+
+public:
+ static const bool value =
+ !is_reference<T>::value
+ && !is_void<T>::value
+ && (sizeof(test<T>(0)) == sizeof(Two));
+};
+
+// warning: we cannot instanciate std::numeric_limits for incomplete types, we use is_abstract_class_or_function
+// prior to the specialization below
template <typename T>
struct tolerance_based_delegate<T, true>
: mpl::bool_<
@@ -68,7 +87,7 @@ struct tolerance_based_delegate<T, true>
* floating point (eg. boost.multiprecision).
*/
template <typename T>
-struct tolerance_based : tolerance_based_delegate<T, !is_array<T>::value >::type {};
+struct tolerance_based : tolerance_based_delegate<T, !is_array<T>::value && !is_abstract_class_or_function<T>::value>::type {};
// ************************************************************************** //
// ************** fpc::strength ************** //
diff --git a/boost/test/unit_test_log_formatter.hpp b/boost/test/unit_test_log_formatter.hpp
index e4648b4dab..6ec72cafa7 100644
--- a/boost/test/unit_test_log_formatter.hpp
+++ b/boost/test/unit_test_log_formatter.hpp
@@ -172,6 +172,7 @@ public:
}
/// Deprecated version of this interface
+ /// @deprecated
virtual void test_unit_skipped( std::ostream& /* os */, test_unit const& /* tu */) {}
/// Invoked when a test unit is aborted
@@ -324,4 +325,3 @@ protected:
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_UNIT_TEST_LOG_FORMATTER_HPP_071894GER
-
diff --git a/boost/test/unit_test_suite.hpp b/boost/test/unit_test_suite.hpp
index f55eff7291..be862ef217 100644
--- a/boost/test/unit_test_suite.hpp
+++ b/boost/test/unit_test_suite.hpp
@@ -376,6 +376,12 @@ BOOST_TEST_APPEND_UNIQUE_ID( BOOST_JOIN( test_name, _registrar ) ) BOOST_ATTRIBU
#if defined(BOOST_TEST_MAIN)
+// initializing the master test suite name from the user defined macros
+// this function should be seen exactly once.
+#ifdef BOOST_TEST_MODULE
+static const boost::unit_test::framework::impl::master_test_suite_name_setter mtsetter(BOOST_TEST_STRINGIZE( BOOST_TEST_MODULE ).trim( "\"" ));
+#endif
+
#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
bool init_unit_test() {
#else
@@ -383,12 +389,6 @@ bool init_unit_test() {
init_unit_test_suite( int, char* [] ) {
#endif
-#ifdef BOOST_TEST_MODULE
- using namespace ::boost::unit_test;
- assign_op( framework::master_test_suite().p_name.value, BOOST_TEST_STRINGIZE( BOOST_TEST_MODULE ).trim( "\"" ), 0 );
-
-#endif
-
#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
return true;
}
diff --git a/boost/thread/concurrent_queues/detail/sync_deque_base.hpp b/boost/thread/concurrent_queues/detail/sync_deque_base.hpp
index e3ecad15de..704efc70c5 100644
--- a/boost/thread/concurrent_queues/detail/sync_deque_base.hpp
+++ b/boost/thread/concurrent_queues/detail/sync_deque_base.hpp
@@ -63,7 +63,7 @@ namespace detail
protected:
mutable mutex mtx_;
- condition_variable not_empty_;
+ condition_variable cond_;
underlying_queue_type data_;
bool closed_;
@@ -91,16 +91,14 @@ namespace detail
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
template <class WClock, class Duration>
queue_op_status wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
- template <class WClock, class Duration>
- queue_op_status wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
- inline void notify_not_empty_if_needed(unique_lock<mutex>& )
+ inline void notify_elem_added(unique_lock<mutex>& )
{
- not_empty_.notify_one();
+ cond_.notify_all();
}
- inline void notify_not_empty_if_needed(lock_guard<mutex>& )
+ inline void notify_elem_added(lock_guard<mutex>& )
{
- not_empty_.notify_one();
+ cond_.notify_all();
}
};
@@ -124,7 +122,7 @@ namespace detail
lock_guard<mutex> lk(mtx_);
closed_ = true;
}
- not_empty_.notify_all();
+ cond_.notify_all();
}
template <class ValueType, class Queue>
@@ -189,7 +187,7 @@ namespace detail
template <class ValueType, class Queue>
bool sync_deque_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk)
{
- not_empty_.wait(lk, boost::bind(&sync_deque_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk)));
+ cond_.wait(lk, boost::bind(&sync_deque_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk)));
if (! empty(lk)) return false; // success
return true; // closed
}
@@ -198,22 +196,12 @@ namespace detail
template <class WClock, class Duration>
queue_op_status sync_deque_base<ValueType, Queue>::wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
{
- if (! not_empty_.wait_until(lk, tp, boost::bind(&sync_deque_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk))))
+ if (! cond_.wait_until(lk, tp, boost::bind(&sync_deque_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk))))
return queue_op_status::timeout;
if (! empty(lk)) return queue_op_status::success;
return queue_op_status::closed;
}
- template <class ValueType, class Queue>
- template <class WClock, class Duration>
- queue_op_status sync_deque_base<ValueType, Queue>::wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
- {
- bool (sync_queue_base<ValueType, Queue>::*closed_function_ptr)(unique_lock<mutex>&) const = &sync_queue_base<ValueType, Queue>::closed;
- if (! not_empty_.wait_until(lk, tp, boost::bind(closed_function_ptr, boost::ref(*this), boost::ref(lk))))
- return queue_op_status::timeout;
- return queue_op_status::closed;
- }
-
} // detail
} // concurrent
} // boost
diff --git a/boost/thread/concurrent_queues/detail/sync_queue_base.hpp b/boost/thread/concurrent_queues/detail/sync_queue_base.hpp
index c570da9505..26d4dcd14a 100644
--- a/boost/thread/concurrent_queues/detail/sync_queue_base.hpp
+++ b/boost/thread/concurrent_queues/detail/sync_queue_base.hpp
@@ -63,7 +63,7 @@ namespace detail
protected:
mutable mutex mtx_;
- condition_variable not_empty_;
+ condition_variable cond_;
underlying_queue_type data_;
bool closed_;
@@ -91,16 +91,14 @@ namespace detail
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
template <class WClock, class Duration>
queue_op_status wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
- template <class WClock, class Duration>
- queue_op_status wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
- inline void notify_not_empty_if_needed(unique_lock<mutex>& )
+ inline void notify_elem_added(unique_lock<mutex>& )
{
- not_empty_.notify_one();
+ cond_.notify_all();
}
- inline void notify_not_empty_if_needed(lock_guard<mutex>& )
+ inline void notify_elem_added(lock_guard<mutex>& )
{
- not_empty_.notify_one();
+ cond_.notify_all();
}
};
@@ -124,7 +122,7 @@ namespace detail
lock_guard<mutex> lk(mtx_);
closed_ = true;
}
- not_empty_.notify_all();
+ cond_.notify_all();
}
template <class ValueType, class Queue>
@@ -189,7 +187,7 @@ namespace detail
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk)
{
- not_empty_.wait(lk, boost::bind(&sync_queue_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk)));
+ cond_.wait(lk, boost::bind(&sync_queue_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk)));
if (! empty(lk)) return false; // success
return true; // closed
}
@@ -198,22 +196,12 @@ namespace detail
template <class WClock, class Duration>
queue_op_status sync_queue_base<ValueType, Queue>::wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
{
- if (! not_empty_.wait_until(lk, tp, boost::bind(&sync_queue_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk))))
+ if (! cond_.wait_until(lk, tp, boost::bind(&sync_queue_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk))))
return queue_op_status::timeout;
if (! empty(lk)) return queue_op_status::success;
return queue_op_status::closed;
}
- template <class ValueType, class Queue>
- template <class WClock, class Duration>
- queue_op_status sync_queue_base<ValueType, Queue>::wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
- {
- bool (sync_queue_base<ValueType, Queue>::*closed_function_ptr)(unique_lock<mutex>&) const = &sync_queue_base<ValueType, Queue>::closed;
- if (! not_empty_.wait_until(lk, tp, boost::bind(closed_function_ptr, boost::ref(*this), boost::ref(lk))))
- return queue_op_status::timeout;
- return queue_op_status::closed;
- }
-
} // detail
} // concurrent
} // boost
diff --git a/boost/thread/concurrent_queues/sync_deque.hpp b/boost/thread/concurrent_queues/sync_deque.hpp
index c6159c4be0..95e36409bd 100644
--- a/boost/thread/concurrent_queues/sync_deque.hpp
+++ b/boost/thread/concurrent_queues/sync_deque.hpp
@@ -92,13 +92,13 @@ namespace concurrent
inline void push_back(const value_type& elem, unique_lock<mutex>& lk)
{
super::data_.push_back(elem);
- super::notify_not_empty_if_needed(lk);
+ super::notify_elem_added(lk);
}
inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
{
super::data_.push_back(boost::move(elem));
- super::notify_not_empty_if_needed(lk);
+ super::notify_elem_added(lk);
}
};
@@ -122,7 +122,7 @@ namespace concurrent
// {
// data_.push(boost::move(*cur));;
// }
-// notify_not_empty_if_needed(lk);
+// notify_elem_added(lk);
// }
// catch (...)
// {
diff --git a/boost/thread/concurrent_queues/sync_priority_queue.hpp b/boost/thread/concurrent_queues/sync_priority_queue.hpp
index 2c6881f90f..f5676335c7 100644
--- a/boost/thread/concurrent_queues/sync_priority_queue.hpp
+++ b/boost/thread/concurrent_queues/sync_priority_queue.hpp
@@ -174,14 +174,14 @@ namespace concurrent
{
super::throw_if_closed(lk);
super::data_.push(elem);
- super::notify_not_empty_if_needed(lk);
+ super::notify_elem_added(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, const T& elem)
{
super::throw_if_closed(lk);
super::data_.push(elem);
- super::notify_not_empty_if_needed(lk);
+ super::notify_elem_added(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(const T& elem)
@@ -196,14 +196,14 @@ namespace concurrent
{
super::throw_if_closed(lk);
super::data_.push(boost::move(elem));
- super::notify_not_empty_if_needed(lk);
+ super::notify_elem_added(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(lock_guard<mutex>& lk, BOOST_THREAD_RV_REF(T) elem)
{
super::throw_if_closed(lk);
super::data_.push(boost::move(elem));
- super::notify_not_empty_if_needed(lk);
+ super::notify_elem_added(lk);
}
template <class T, class Container,class Cmp>
void sync_priority_queue<T,Container,Cmp>::push(BOOST_THREAD_RV_REF(T) elem)
diff --git a/boost/thread/concurrent_queues/sync_queue.hpp b/boost/thread/concurrent_queues/sync_queue.hpp
index b36b57e607..ac0fe68d77 100644
--- a/boost/thread/concurrent_queues/sync_queue.hpp
+++ b/boost/thread/concurrent_queues/sync_queue.hpp
@@ -92,13 +92,13 @@ namespace concurrent
inline void push(const value_type& elem, unique_lock<mutex>& lk)
{
super::data_.push_back(elem);
- super::notify_not_empty_if_needed(lk);
+ super::notify_elem_added(lk);
}
inline void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock<mutex>& lk)
{
super::data_.push_back(boost::move(elem));
- super::notify_not_empty_if_needed(lk);
+ super::notify_elem_added(lk);
}
};
@@ -122,7 +122,7 @@ namespace concurrent
// {
// data_.push(boost::move(*cur));;
// }
-// notify_not_empty_if_needed(lk);
+// notify_elem_added(lk);
// }
// catch (...)
// {
diff --git a/boost/thread/concurrent_queues/sync_timed_queue.hpp b/boost/thread/concurrent_queues/sync_timed_queue.hpp
index a4394c0729..fd8d5a3c46 100644
--- a/boost/thread/concurrent_queues/sync_timed_queue.hpp
+++ b/boost/thread/concurrent_queues/sync_timed_queue.hpp
@@ -16,6 +16,8 @@
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/chrono_io.hpp>
+#include <algorithm> // std::min
+
#include <boost/config/abi_prefix.hpp>
namespace boost
@@ -59,6 +61,45 @@ namespace detail
}
}; //end struct
+ template <class Duration>
+ chrono::time_point<chrono::steady_clock,Duration>
+ limit_timepoint(chrono::time_point<chrono::steady_clock,Duration> const& tp)
+ {
+ // Clock == chrono::steady_clock
+ return tp;
+ }
+
+ template <class Clock, class Duration>
+ chrono::time_point<Clock,Duration>
+ limit_timepoint(chrono::time_point<Clock,Duration> const& tp)
+ {
+ // Clock != chrono::steady_clock
+ // The system time may jump while wait_until() is waiting. To compensate for this and time out near
+ // the correct time, we limit how long wait_until() can wait before going around the loop again.
+ const chrono::time_point<Clock,Duration> tpmax(chrono::time_point_cast<Duration>(Clock::now() + chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
+ return (std::min)(tp, tpmax);
+ }
+
+ template <class Duration>
+ chrono::steady_clock::time_point
+ convert_to_steady_clock_timepoint(chrono::time_point<chrono::steady_clock,Duration> const& tp)
+ {
+ // Clock == chrono::steady_clock
+ return chrono::time_point_cast<chrono::steady_clock::duration>(tp);
+ }
+
+ template <class Clock, class Duration>
+ chrono::steady_clock::time_point
+ convert_to_steady_clock_timepoint(chrono::time_point<Clock,Duration> const& tp)
+ {
+ // Clock != chrono::steady_clock
+ // The system time may jump while wait_until() is waiting. To compensate for this and time out near
+ // the correct time, we limit how long wait_until() can wait before going around the loop again.
+ const chrono::steady_clock::duration dura(chrono::duration_cast<chrono::steady_clock::duration>(tp - Clock::now()));
+ const chrono::steady_clock::duration duramax(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
+ return chrono::steady_clock::now() + (std::min)(dura, duramax);
+ }
+
} //end detail namespace
template <class T, class Clock = chrono::steady_clock, class TimePoint=typename Clock::time_point>
@@ -88,8 +129,8 @@ namespace detail
T pull();
void pull(T& elem);
- template <class WClock, class Duration>
- queue_op_status pull_until(chrono::time_point<WClock,Duration> const& tp, T& elem);
+ template <class Duration>
+ queue_op_status pull_until(chrono::time_point<clock,Duration> const& tp, T& elem);
template <class Rep, class Period>
queue_op_status pull_for(chrono::duration<Rep,Period> const& dura, T& elem);
@@ -122,8 +163,9 @@ namespace detail
inline bool not_empty_and_time_reached(lock_guard<mutex>& lk) const;
bool wait_to_pull(unique_lock<mutex>&);
- template <class WClock, class Duration>
- queue_op_status wait_to_pull_until(unique_lock<mutex>&, chrono::time_point<WClock, Duration> const& tp);
+ queue_op_status wait_to_pull_until(unique_lock<mutex>&, TimePoint const& tp);
+ template <class Rep, class Period>
+ queue_op_status wait_to_pull_for(unique_lock<mutex>& lk, chrono::duration<Rep,Period> const& dura);
T pull(unique_lock<mutex>&);
T pull(lock_guard<mutex>&);
@@ -228,14 +270,13 @@ namespace detail
if (not_empty_and_time_reached(lk)) return false; // success
if (super::closed(lk)) return true; // closed
- const time_point tp(super::data_.top().time);
- super::wait_until_closed_until(lk, tp);
+ const time_point tpmin(detail::limit_timepoint(super::data_.top().time));
+ super::cond_.wait_until(lk, tpmin);
}
}
template <class T, class Clock, class TimePoint>
- template <class WClock, class Duration>
- queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_to_pull_until(unique_lock<mutex>& lk, chrono::time_point<WClock, Duration> const& tp)
+ queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_to_pull_until(unique_lock<mutex>& lk, TimePoint const& tp)
{
for (;;)
{
@@ -249,8 +290,30 @@ namespace detail
if (super::closed(lk)) return queue_op_status::closed;
if (clock::now() >= tp) return super::empty(lk) ? queue_op_status::timeout : queue_op_status::not_ready;
- const time_point tpmin(tp < super::data_.top().time ? tp : super::data_.top().time);
- super::wait_until_closed_until(lk, tpmin);
+ const time_point tpmin((std::min)(tp, detail::limit_timepoint(super::data_.top().time)));
+ super::cond_.wait_until(lk, tpmin);
+ }
+ }
+
+ template <class T, class Clock, class TimePoint>
+ template <class Rep, class Period>
+ queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_to_pull_for(unique_lock<mutex>& lk, chrono::duration<Rep,Period> const& dura)
+ {
+ const chrono::steady_clock::time_point tp(chrono::steady_clock::now() + chrono::duration_cast<chrono::steady_clock::duration>(dura));
+ for (;;)
+ {
+ if (not_empty_and_time_reached(lk)) return queue_op_status::success;
+ if (super::closed(lk)) return queue_op_status::closed;
+ if (chrono::steady_clock::now() >= tp) return super::empty(lk) ? queue_op_status::timeout : queue_op_status::not_ready;
+
+ super::wait_until_not_empty_or_closed_until(lk, tp);
+
+ if (not_empty_and_time_reached(lk)) return queue_op_status::success;
+ if (super::closed(lk)) return queue_op_status::closed;
+ if (chrono::steady_clock::now() >= tp) return super::empty(lk) ? queue_op_status::timeout : queue_op_status::not_ready;
+
+ const chrono::steady_clock::time_point tpmin((std::min)(tp, detail::convert_to_steady_clock_timepoint(super::data_.top().time)));
+ super::cond_.wait_until(lk, tpmin);
}
}
@@ -315,12 +378,12 @@ namespace detail
//////////////////////
template <class T, class Clock, class TimePoint>
- template <class WClock, class Duration>
+ template <class Duration>
queue_op_status
- sync_timed_queue<T, Clock, TimePoint>::pull_until(chrono::time_point<WClock, Duration> const& tp, T& elem)
+ sync_timed_queue<T, Clock, TimePoint>::pull_until(chrono::time_point<clock,Duration> const& tp, T& elem)
{
unique_lock<mutex> lk(super::mtx_);
- const queue_op_status rc = wait_to_pull_until(lk, tp);
+ const queue_op_status rc = wait_to_pull_until(lk, chrono::time_point_cast<typename time_point::duration>(tp));
if (rc == queue_op_status::success) pull(lk, elem);
return rc;
}
@@ -331,7 +394,10 @@ namespace detail
queue_op_status
sync_timed_queue<T, Clock, TimePoint>::pull_for(chrono::duration<Rep,Period> const& dura, T& elem)
{
- return pull_until(chrono::steady_clock::now() + dura, elem);
+ unique_lock<mutex> lk(super::mtx_);
+ const queue_op_status rc = wait_to_pull_for(lk, dura);
+ if (rc == queue_op_status::success) pull(lk, elem);
+ return rc;
}
///////////////////////////
diff --git a/boost/thread/pthread/condition_variable.hpp b/boost/thread/pthread/condition_variable.hpp
index 63f4183471..e3c511f26a 100644
--- a/boost/thread/pthread/condition_variable.hpp
+++ b/boost/thread/pthread/condition_variable.hpp
@@ -76,18 +76,18 @@ namespace boost
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
pthread_mutex_t* the_mutex = &internal_mutex;
guard.activate(m);
- res = pthread_cond_wait(&cond,the_mutex);
+ res = posix::pthread_cond_wait(&cond,the_mutex);
check_for_interruption.unlock_if_locked();
guard.deactivate();
#else
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
- res = pthread_cond_wait(&cond,the_mutex);
+ res = posix::pthread_cond_wait(&cond,the_mutex);
#endif
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
#endif
- if(res && res != EINTR)
+ if(res)
{
boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_wait"));
}
@@ -119,12 +119,12 @@ namespace boost
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
pthread_mutex_t* the_mutex = &internal_mutex;
guard.activate(m);
- cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout.getTs());
+ cond_res=posix::pthread_cond_timedwait(&cond,the_mutex,&timeout.getTs());
check_for_interruption.unlock_if_locked();
guard.deactivate();
#else
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
- cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout.getTs());
+ cond_res=posix::pthread_cond_timedwait(&cond,the_mutex,&timeout.getTs());
#endif
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
@@ -146,7 +146,7 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
#endif
- BOOST_VERIFY(!pthread_cond_signal(&cond));
+ BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
}
inline void condition_variable::notify_all() BOOST_NOEXCEPT
@@ -154,7 +154,7 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
#endif
- BOOST_VERIFY(!pthread_cond_broadcast(&cond));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&cond));
}
class condition_variable_any
@@ -166,22 +166,22 @@ namespace boost
BOOST_THREAD_NO_COPYABLE(condition_variable_any)
condition_variable_any()
{
- int const res=pthread_mutex_init(&internal_mutex,NULL);
+ int const res=posix::pthread_mutex_init(&internal_mutex);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init"));
}
- int const res2 = pthread::cond_init(cond);
+ int const res2 = posix::pthread_cond_init(&cond);
if(res2)
{
- BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
- boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread::cond_init"));
+ BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
+ boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread_cond_init"));
}
}
~condition_variable_any()
{
- BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
- BOOST_VERIFY(!pthread_cond_destroy(&cond));
+ BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
+ BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
}
template<typename lock_type>
@@ -196,7 +196,7 @@ namespace boost
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
#endif
guard.activate(m);
- res=pthread_cond_wait(&cond,&internal_mutex);
+ res=posix::pthread_cond_wait(&cond,&internal_mutex);
check_for_interruption.unlock_if_locked();
guard.deactivate();
}
@@ -438,13 +438,13 @@ namespace boost
void notify_one() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
- BOOST_VERIFY(!pthread_cond_signal(&cond));
+ BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
}
void notify_all() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
- BOOST_VERIFY(!pthread_cond_broadcast(&cond));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&cond));
}
private:
@@ -471,7 +471,7 @@ namespace boost
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
#endif
guard.activate(m);
- res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout.getTs());
+ res=posix::pthread_cond_timedwait(&cond,&internal_mutex,&timeout.getTs());
check_for_interruption.unlock_if_locked();
guard.deactivate();
}
diff --git a/boost/thread/pthread/condition_variable_fwd.hpp b/boost/thread/pthread/condition_variable_fwd.hpp
index 08b1583463..f5963486f8 100644
--- a/boost/thread/pthread/condition_variable_fwd.hpp
+++ b/boost/thread/pthread/condition_variable_fwd.hpp
@@ -58,36 +58,29 @@ namespace boost
// above) and must be initialized (etc) in case some
// compilation units provide interruptions and others
// don't.
- res=pthread_mutex_init(&internal_mutex,NULL);
+ res=posix::pthread_mutex_init(&internal_mutex);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
}
//#endif
- res = pthread::cond_init(cond);
+ res = posix::pthread_cond_init(&cond);
if (res)
{
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// ditto
- BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
+ BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
//#endif
- boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread::cond_init"));
+ boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_cond_init"));
}
}
~condition_variable()
{
- int ret;
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// ditto
- do {
- ret = pthread_mutex_destroy(&internal_mutex);
- } while (ret == EINTR);
- BOOST_ASSERT(!ret);
+ BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
//#endif
- do {
- ret = pthread_cond_destroy(&cond);
- } while (ret == EINTR);
- BOOST_ASSERT(!ret);
+ BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
}
void wait(unique_lock<mutex>& m);
diff --git a/boost/thread/pthread/mutex.hpp b/boost/thread/pthread/mutex.hpp
index ecf80c28eb..94a7388807 100644
--- a/boost/thread/pthread/mutex.hpp
+++ b/boost/thread/pthread/mutex.hpp
@@ -33,10 +33,6 @@
#include <boost/config/abi_prefix.hpp>
-#ifndef BOOST_THREAD_HAS_NO_EINTR_BUG
-#define BOOST_THREAD_HAS_EINTR_BUG
-#endif
-
namespace boost
{
@@ -49,7 +45,7 @@ namespace boost
mutex()
{
- int const res=pthread_mutex_init(&m,NULL);
+ int const res=posix::pthread_mutex_init(&m);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init"));
@@ -57,9 +53,7 @@ namespace boost
}
~mutex()
{
- int const res = posix::pthread_mutex_destroy(&m);
- boost::ignore_unused(res);
- BOOST_ASSERT(!res);
+ BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
}
void lock() BOOST_THREAD_ACQUIRE()
@@ -73,22 +67,12 @@ namespace boost
void unlock() BOOST_THREAD_RELEASE()
{
- int res = posix::pthread_mutex_unlock(&m);
- (void)res;
- BOOST_ASSERT(res == 0);
-// if (res)
-// {
-// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
-// }
+ BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
}
bool try_lock() BOOST_THREAD_TRY_ACQUIRE(true)
{
- int res;
- do
- {
- res = posix::pthread_mutex_trylock(&m);
- } while (res == EINTR);
+ int res = posix::pthread_mutex_trylock(&m);
if (res==EBUSY)
{
return false;
@@ -124,17 +108,17 @@ namespace boost
BOOST_THREAD_NO_COPYABLE(timed_mutex)
timed_mutex()
{
- int const res=pthread_mutex_init(&m,NULL);
+ int const res=posix::pthread_mutex_init(&m);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init"));
}
#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
- int const res2=pthread::cond_init(cond);
+ int const res2=posix::pthread_cond_init(&cond);
if(res2)
{
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
- boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread::cond_init"));
+ boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init"));
}
is_locked=false;
#endif
@@ -143,7 +127,7 @@ namespace boost
{
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
- BOOST_VERIFY(!pthread_cond_destroy(&cond));
+ BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
#endif
}
@@ -192,22 +176,12 @@ namespace boost
void unlock()
{
- int res = posix::pthread_mutex_unlock(&m);
- (void)res;
- BOOST_ASSERT(res == 0);
-// if (res)
-// {
-// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
-// }
+ BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
}
bool try_lock()
{
- int res;
- do
- {
- res = posix::pthread_mutex_trylock(&m);
- } while (res == EINTR);
+ int res = posix::pthread_mutex_trylock(&m);
if (res==EBUSY)
{
return false;
@@ -261,7 +235,7 @@ namespace boost
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
while(is_locked)
{
- int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout.getTs());
+ int const cond_res=posix::pthread_cond_timedwait(&cond,&m,&timeout.getTs());
if(cond_res==ETIMEDOUT)
{
break;
diff --git a/boost/thread/pthread/once.hpp b/boost/thread/pthread/once.hpp
index 0bef0387de..515b78eef2 100644
--- a/boost/thread/pthread/once.hpp
+++ b/boost/thread/pthread/once.hpp
@@ -14,6 +14,7 @@
#include <boost/thread/detail/move.hpp>
#include <boost/thread/detail/invoke.hpp>
+#include <boost/thread/pthread/pthread_helpers.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/core/no_exceptions_support.hpp>
@@ -149,18 +150,18 @@ namespace boost
BOOST_CATCH (...)
{
flag.epoch=uninitialized_flag;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
BOOST_RETHROW
}
BOOST_CATCH_END
flag.epoch=--thread_detail::once_global_epoch;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
- BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
}
}
}
@@ -194,18 +195,18 @@ namespace boost
BOOST_CATCH (...)
{
flag.epoch=uninitialized_flag;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
BOOST_RETHROW
}
BOOST_CATCH_END
flag.epoch=--thread_detail::once_global_epoch;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
- BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
}
}
}
@@ -238,18 +239,18 @@ namespace boost
BOOST_CATCH (...)
{
flag.epoch=uninitialized_flag;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
BOOST_RETHROW
}
BOOST_CATCH_END
flag.epoch=--thread_detail::once_global_epoch;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
- BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
}
}
}
@@ -281,18 +282,18 @@ namespace boost
BOOST_CATCH (...)
{
flag.epoch=uninitialized_flag;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
BOOST_RETHROW
}
BOOST_CATCH_END
flag.epoch=--thread_detail::once_global_epoch;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
- BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
}
}
}
@@ -325,18 +326,18 @@ namespace boost
BOOST_CATCH (...)
{
flag.epoch=uninitialized_flag;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
BOOST_RETHROW
}
BOOST_CATCH_END
flag.epoch=--thread_detail::once_global_epoch;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
- BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
}
}
}
@@ -369,18 +370,18 @@ namespace boost
BOOST_CATCH (...)
{
flag.epoch=uninitialized_flag;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
BOOST_RETHROW
}
BOOST_CATCH_END
flag.epoch=--thread_detail::once_global_epoch;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
- BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
}
}
}
@@ -416,18 +417,18 @@ namespace boost
BOOST_CATCH (...)
{
flag.epoch=uninitialized_flag;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
BOOST_RETHROW
}
BOOST_CATCH_END
flag.epoch=--thread_detail::once_global_epoch;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
- BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
}
}
}
@@ -463,18 +464,18 @@ namespace boost
BOOST_CATCH (...)
{
flag.epoch=uninitialized_flag;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
BOOST_RETHROW
}
BOOST_CATCH_END
flag.epoch=--thread_detail::once_global_epoch;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
- BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
}
}
}
@@ -512,18 +513,18 @@ namespace boost
BOOST_CATCH (...)
{
flag.epoch=uninitialized_flag;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
BOOST_RETHROW
}
BOOST_CATCH_END
flag.epoch=--thread_detail::once_global_epoch;
- BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv));
+ BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
- BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
+ BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
}
}
}
diff --git a/boost/thread/pthread/pthread_helpers.hpp b/boost/thread/pthread/pthread_helpers.hpp
index c1ff0f9239..6809994165 100644
--- a/boost/thread/pthread/pthread_helpers.hpp
+++ b/boost/thread/pthread/pthread_helpers.hpp
@@ -8,33 +8,178 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
+#include <boost/throw_exception.hpp>
#include <pthread.h>
+#include <errno.h>
#include <boost/config/abi_prefix.hpp>
+#ifndef BOOST_THREAD_HAS_NO_EINTR_BUG
+#define BOOST_THREAD_HAS_EINTR_BUG
+#endif
+
namespace boost
{
- namespace pthread
- {
- inline int cond_init(pthread_cond_t& cond) {
-
- #ifdef BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
- pthread_condattr_t attr;
- int res = pthread_condattr_init(&attr);
- if (res)
- {
- return res;
- }
- pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
- res=pthread_cond_init(&cond,&attr);
- pthread_condattr_destroy(&attr);
- return res;
- #else
- return pthread_cond_init(&cond,NULL);
- #endif
+ namespace posix
+ {
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_mutex_init(pthread_mutex_t* m, const pthread_mutexattr_t* attr = NULL)
+ {
+ return ::pthread_mutex_init(m, attr);
+ }
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_cond_init(pthread_cond_t* c)
+ {
+#ifdef BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
+ pthread_condattr_t attr;
+ int res = pthread_condattr_init(&attr);
+ if (res)
+ {
+ return res;
}
+ BOOST_VERIFY(!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
+ res = ::pthread_cond_init(c, &attr);
+ BOOST_VERIFY(!pthread_condattr_destroy(&attr));
+ return res;
+#else
+ return ::pthread_cond_init(c, NULL);
+#endif
+ }
+
+#ifdef BOOST_THREAD_HAS_EINTR_BUG
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_mutex_destroy(pthread_mutex_t* m)
+ {
+ int ret;
+ do
+ {
+ ret = ::pthread_mutex_destroy(m);
+ } while (ret == EINTR);
+ return ret;
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_cond_destroy(pthread_cond_t* c)
+ {
+ int ret;
+ do
+ {
+ ret = ::pthread_cond_destroy(c);
+ } while (ret == EINTR);
+ return ret;
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_mutex_lock(pthread_mutex_t* m)
+ {
+ int ret;
+ do
+ {
+ ret = ::pthread_mutex_lock(m);
+ } while (ret == EINTR);
+ return ret;
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_mutex_trylock(pthread_mutex_t* m)
+ {
+ int ret;
+ do
+ {
+ ret = ::pthread_mutex_trylock(m);
+ } while (ret == EINTR);
+ return ret;
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_mutex_unlock(pthread_mutex_t* m)
+ {
+ int ret;
+ do
+ {
+ ret = ::pthread_mutex_unlock(m);
+ } while (ret == EINTR);
+ return ret;
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_cond_wait(pthread_cond_t* c, pthread_mutex_t* m)
+ {
+ int ret;
+ do
+ {
+ ret = ::pthread_cond_wait(c, m);
+ } while (ret == EINTR);
+ return ret;
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_cond_timedwait(pthread_cond_t* c, pthread_mutex_t* m, const struct timespec* t)
+ {
+ int ret;
+ do
+ {
+ ret = ::pthread_cond_timedwait(c, m, t);
+ } while (ret == EINTR);
+ return ret;
+ }
+#else
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_mutex_destroy(pthread_mutex_t* m)
+ {
+ return ::pthread_mutex_destroy(m);
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_cond_destroy(pthread_cond_t* c)
+ {
+ return ::pthread_cond_destroy(c);
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_mutex_lock(pthread_mutex_t* m)
+ {
+ return ::pthread_mutex_lock(m);
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_mutex_trylock(pthread_mutex_t* m)
+ {
+ return ::pthread_mutex_trylock(m);
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_mutex_unlock(pthread_mutex_t* m)
+ {
+ return ::pthread_mutex_unlock(m);
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_cond_wait(pthread_cond_t* c, pthread_mutex_t* m)
+ {
+ return ::pthread_cond_wait(c, m);
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_cond_timedwait(pthread_cond_t* c, pthread_mutex_t* m, const struct timespec* t)
+ {
+ return ::pthread_cond_timedwait(c, m, t);
+ }
+#endif
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_cond_signal(pthread_cond_t* c)
+ {
+ return ::pthread_cond_signal(c);
+ }
+
+ BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
+ int pthread_cond_broadcast(pthread_cond_t* c)
+ {
+ return ::pthread_cond_broadcast(c);
}
+ }
}
#include <boost/config/abi_suffix.hpp>
diff --git a/boost/thread/pthread/pthread_mutex_scoped_lock.hpp b/boost/thread/pthread/pthread_mutex_scoped_lock.hpp
index dbbb0202ae..4823254621 100644
--- a/boost/thread/pthread/pthread_mutex_scoped_lock.hpp
+++ b/boost/thread/pthread/pthread_mutex_scoped_lock.hpp
@@ -8,80 +8,12 @@
#include <pthread.h>
#include <boost/assert.hpp>
+#include <boost/thread/pthread/pthread_helpers.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
-namespace posix {
-#ifdef BOOST_THREAD_HAS_EINTR_BUG
- BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
- int pthread_mutex_destroy(pthread_mutex_t* m)
- {
- int ret;
- do
- {
- ret = ::pthread_mutex_destroy(m);
- } while (ret == EINTR);
- return ret;
- }
- BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
- int pthread_mutex_lock(pthread_mutex_t* m)
- {
- int ret;
- do
- {
- ret = ::pthread_mutex_lock(m);
- } while (ret == EINTR);
- return ret;
- }
- BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
- int pthread_mutex_unlock(pthread_mutex_t* m)
- {
- int ret;
- do
- {
- ret = ::pthread_mutex_unlock(m);
- } while (ret == EINTR);
- return ret;
- }
-#else
- BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
- int pthread_mutex_destroy(pthread_mutex_t* m)
- {
- return ::pthread_mutex_destroy(m);
- }
- BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
- int pthread_mutex_lock(pthread_mutex_t* m)
- {
- return ::pthread_mutex_lock(m);
- }
- BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
- int pthread_mutex_unlock(pthread_mutex_t* m)
- {
- return ::pthread_mutex_unlock(m);
- }
-
-#endif
- BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
- int pthread_mutex_trylock(pthread_mutex_t* m)
- {
- return ::pthread_mutex_trylock(m);
- }
-
- BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
- int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
- {
- return ::pthread_cond_wait(cond, mutex);
- }
- BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
- int pthread_cond_signal(pthread_cond_t *cond)
- {
- return ::pthread_cond_signal(cond);
- }
-
-
-}
namespace pthread
{
class pthread_mutex_scoped_lock
diff --git a/boost/thread/pthread/recursive_mutex.hpp b/boost/thread/pthread/recursive_mutex.hpp
index f349cacf7e..2aaf425bff 100644
--- a/boost/thread/pthread/recursive_mutex.hpp
+++ b/boost/thread/pthread/recursive_mutex.hpp
@@ -71,7 +71,7 @@ namespace boost
boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_settype"));
}
- int const res=pthread_mutex_init(&m,&attr);
+ int const res=posix::pthread_mutex_init(&m,&attr);
if(res)
{
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
@@ -79,16 +79,16 @@ namespace boost
}
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
#else
- int const res=pthread_mutex_init(&m,NULL);
+ int const res=posix::pthread_mutex_init(&m);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
}
- int const res2=pthread::cond_init(cond);
+ int const res2=posix::pthread_cond_init(&cond);
if(res2)
{
- BOOST_VERIFY(!pthread_mutex_destroy(&m));
- boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread::cond_init"));
+ BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
+ boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init"));
}
is_locked=false;
count=0;
@@ -96,9 +96,9 @@ namespace boost
}
~recursive_mutex()
{
- BOOST_VERIFY(!pthread_mutex_destroy(&m));
+ BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
- BOOST_VERIFY(!pthread_cond_destroy(&cond));
+ BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
#endif
}
@@ -138,7 +138,7 @@ namespace boost
while(is_locked)
{
- BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
+ BOOST_VERIFY(!posix::pthread_cond_wait(&cond,&m));
}
is_locked=true;
++count;
@@ -152,7 +152,7 @@ namespace boost
{
is_locked=false;
}
- BOOST_VERIFY(!pthread_cond_signal(&cond));
+ BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
}
bool try_lock()
@@ -206,7 +206,7 @@ namespace boost
boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_settype"));
}
- int const res=pthread_mutex_init(&m,&attr);
+ int const res=posix::pthread_mutex_init(&m,&attr);
if(res)
{
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
@@ -214,16 +214,16 @@ namespace boost
}
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
#else
- int const res=pthread_mutex_init(&m,NULL);
+ int const res=posix::pthread_mutex_init(&m);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
}
- int const res2=pthread::cond_init(cond);
+ int const res2=posix::pthread_cond_init(&cond);
if(res2)
{
- BOOST_VERIFY(!pthread_mutex_destroy(&m));
- boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread::cond_init"));
+ BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
+ boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init"));
}
is_locked=false;
count=0;
@@ -231,9 +231,9 @@ namespace boost
}
~recursive_timed_mutex()
{
- BOOST_VERIFY(!pthread_mutex_destroy(&m));
+ BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
- BOOST_VERIFY(!pthread_cond_destroy(&cond));
+ BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
#endif
}
@@ -306,7 +306,7 @@ namespace boost
while(is_locked)
{
- BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
+ BOOST_VERIFY(!posix::pthread_cond_wait(&cond,&m));
}
is_locked=true;
++count;
@@ -320,7 +320,7 @@ namespace boost
{
is_locked=false;
}
- BOOST_VERIFY(!pthread_cond_signal(&cond));
+ BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
}
bool try_lock() BOOST_NOEXCEPT
@@ -347,7 +347,7 @@ namespace boost
}
while(is_locked)
{
- int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout.getTs());
+ int const cond_res=posix::pthread_cond_timedwait(&cond,&m,&timeout.getTs());
if(cond_res==ETIMEDOUT)
{
break;
diff --git a/boost/thread/pthread/thread_data.hpp b/boost/thread/pthread/thread_data.hpp
index 588e997f89..aefbeb43cf 100644
--- a/boost/thread/pthread/thread_data.hpp
+++ b/boost/thread/pthread/thread_data.hpp
@@ -12,7 +12,7 @@
#include <boost/thread/lock_types.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/pthread/condition_variable_fwd.hpp>
-#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
+#include <boost/thread/pthread/pthread_helpers.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
diff --git a/boost/thread/win32/thread_primitives.hpp b/boost/thread/win32/thread_primitives.hpp
index e0751401d8..391d737584 100644
--- a/boost/thread/win32/thread_primitives.hpp
+++ b/boost/thread/win32/thread_primitives.hpp
@@ -102,7 +102,7 @@ namespace boost
handle const res = ::boost::winapi::CreateEventExW(
0,
mutex_name,
- type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0,
+ (type ? create_event_manual_reset : 0) | (state ? create_event_initial_set : 0),
event_all_access);
#endif
return res;
diff --git a/boost/throw_exception.hpp b/boost/throw_exception.hpp
index c6623e1965..cd77eadea1 100644
--- a/boost/throw_exception.hpp
+++ b/boost/throw_exception.hpp
@@ -54,7 +54,7 @@ namespace boost
{
#ifdef BOOST_NO_EXCEPTIONS
-void throw_exception( std::exception const & e ); // user defined
+BOOST_NORETURN void throw_exception( std::exception const & e ); // user defined
#else
diff --git a/boost/type_traits/detail/config.hpp b/boost/type_traits/detail/config.hpp
index 00970f214f..7c4b4f2162 100644
--- a/boost/type_traits/detail/config.hpp
+++ b/boost/type_traits/detail/config.hpp
@@ -93,6 +93,20 @@
# define BOOST_TT_NO_DEDUCED_NOEXCEPT_PARAM
# define BOOST_TT_NO_NOEXCEPT_SEPARATE_TYPE
#endif
+//
+// If we have the SD6 macros (check for C++11's __cpp_rvalue_references), and we don't have __cpp_noexcept_function_type
+// set, then don't treat noexcept functions as seperate types. This is a fix for msvc with the /Zc:noexceptTypes- flag set.
+//
+#if defined(__cpp_rvalue_references) && !defined(__cpp_noexcept_function_type) && !defined(BOOST_TT_NO_NOEXCEPT_SEPARATE_TYPE)
+# define BOOST_TT_NO_NOEXCEPT_SEPARATE_TYPE
+#endif
+//
+// Check MSVC specific macro on older msvc compilers that don't support the SD6 macros, we don't rely on this
+// if the SD6 macros *are* available as it appears to be undocumented.
+//
+#if defined(BOOST_MSVC) && !defined(__cpp_rvalue_references) && !defined(BOOST_TT_NO_NOEXCEPT_SEPARATE_TYPE) && !defined(_NOEXCEPT_TYPES_SUPPORTED)
+# define BOOST_TT_NO_NOEXCEPT_SEPARATE_TYPE
+#endif
#endif // BOOST_TT_CONFIG_HPP_INCLUDED
diff --git a/boost/type_traits/detail/is_function_cxx_11.hpp b/boost/type_traits/detail/is_function_cxx_11.hpp
index 432af4eccd..4de74a7373 100644
--- a/boost/type_traits/detail/is_function_cxx_11.hpp
+++ b/boost/type_traits/detail/is_function_cxx_11.hpp
@@ -376,7 +376,7 @@ namespace boost {
template <class Ret, class ...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret(Args..., ...)const volatile && BOOST_TT_NOEXCEPT_DECL> : public true_type {};
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(_M_ARM) && !defined(_M_ARM64)
#ifdef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __clrcall(Args...)BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -384,9 +384,11 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...)BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...)BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...)BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -399,9 +401,11 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...)const BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...)const BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...)const BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -414,9 +418,11 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...)volatile BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...)volatile BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...)volatile BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -429,9 +435,11 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...)const volatile BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...)const volatile BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...)const volatile BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -445,9 +453,11 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...)&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...)&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...)&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -460,9 +470,11 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...)const &BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...)const &BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...)const &BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -475,9 +487,11 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...)volatile &BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...)volatile &BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...)volatile &BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -490,9 +504,11 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...)const volatile &BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...)const volatile &BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...)const volatile &BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -506,9 +522,11 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...) && BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...) && BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...) && BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -521,9 +539,11 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...)const &&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...)const &&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...)const &&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -536,9 +556,11 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...)volatile &&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...)volatile &&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...)volatile &&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
@@ -551,15 +573,17 @@ namespace boost {
#ifndef _M_AMD64
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __stdcall(Args...)const volatile &&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
+#ifndef __CLR_VER
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __fastcall(Args...)const volatile &&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
+#endif
#if !defined(__CLR_VER) && (defined(_M_IX86_FP) && (_M_IX86_FP >= 2) || defined(_M_X64))
template <class Ret, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_function<Ret __vectorcall(Args...)const volatile &&BOOST_TT_NOEXCEPT_DECL> : public true_type {};
#endif
-#endif // _MSC_VER
+#endif // defined(_MSC_VER) && !defined(_M_ARM) && !defined(_M_ARM64)
#endif
diff --git a/boost/type_traits/detail/is_member_function_pointer_cxx_11.hpp b/boost/type_traits/detail/is_member_function_pointer_cxx_11.hpp
index d88a004b2c..b0502cbe8b 100644
--- a/boost/type_traits/detail/is_member_function_pointer_cxx_11.hpp
+++ b/boost/type_traits/detail/is_member_function_pointer_cxx_11.hpp
@@ -419,7 +419,7 @@ namespace boost {
template <class Ret, class C, class ...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_member_function_pointer<Ret(C::*)(Args..., ...)const volatile && BOOST_TT_NOEXCEPT_DECL> : public true_type {};
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(_M_ARM) && !defined(_M_ARM64)
#ifdef __CLR_VER
template <class Ret, class C, class...Args BOOST_TT_NOEXCEPT_PARAM>
struct is_member_function_pointer<Ret(__clrcall C::*)(Args...)BOOST_TT_NOEXCEPT_DECL> : public true_type {};
diff --git a/boost/utility/ostream_string.hpp b/boost/utility/ostream_string.hpp
new file mode 100644
index 0000000000..8722e58a2c
--- /dev/null
+++ b/boost/utility/ostream_string.hpp
@@ -0,0 +1,95 @@
+/*
+Copyright 2019 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_UTILITY_OSTREAM_STRING_HPP
+#define BOOST_UTILITY_OSTREAM_STRING_HPP
+
+#include <boost/config.hpp>
+#include <iosfwd>
+#include <cstddef>
+
+namespace boost {
+namespace detail {
+
+template<class charT, class traits>
+inline std::size_t
+oss_put(std::basic_ostream<charT, traits>& os, const charT* data,
+ std::size_t size)
+{
+ return static_cast<std::size_t>(os.rdbuf()->sputn(data, size));
+}
+
+template<class charT, class traits>
+inline bool
+oss_fill(std::basic_ostream<charT, traits>& os, std::size_t size)
+{
+ charT c = os.fill();
+ charT fill[] = { c, c, c, c, c, c, c, c };
+ enum {
+ chunk = sizeof fill / sizeof(charT)
+ };
+ for (; size > chunk; size -= chunk) {
+ if (boost::detail::oss_put(os, fill, chunk) != chunk) {
+ return false;
+ }
+ }
+ return boost::detail::oss_put(os, fill, size) == size;
+}
+
+template<class charT, class traits>
+class oss_guard {
+public:
+ explicit oss_guard(std::basic_ostream<charT, traits>& os) BOOST_NOEXCEPT
+ : os_(&os) { }
+ ~oss_guard() BOOST_NOEXCEPT_IF(false) {
+ if (os_) {
+ os_->setstate(std::basic_ostream<charT, traits>::badbit);
+ }
+ }
+ void release() BOOST_NOEXCEPT {
+ os_ = 0;
+ }
+private:
+ oss_guard(const oss_guard&);
+ oss_guard& operator=(const oss_guard&);
+ std::basic_ostream<charT, traits>* os_;
+};
+
+} /* detail */
+
+template<class charT, class traits>
+inline std::basic_ostream<charT, traits>&
+ostream_string(std::basic_ostream<charT, traits>& os, const charT* data,
+ std::size_t size)
+{
+ typedef std::basic_ostream<charT, traits> stream;
+ detail::oss_guard<charT, traits> guard(os);
+ typename stream::sentry entry(os);
+ if (entry) {
+ std::size_t width = static_cast<std::size_t>(os.width());
+ if (width <= size) {
+ if (detail::oss_put(os, data, size) != size) {
+ return os;
+ }
+ } else if ((os.flags() & stream::adjustfield) == stream::left) {
+ if (detail::oss_put(os, data, size) != size ||
+ !detail::oss_fill(os, width - size)) {
+ return os;
+ }
+ } else if (!detail::oss_fill(os, width - size) ||
+ detail::oss_put(os, data, size) != size) {
+ return os;
+ }
+ os.width(0);
+ }
+ guard.release();
+ return os;
+}
+
+} /* boost */
+
+#endif
diff --git a/boost/utility/string_ref.hpp b/boost/utility/string_ref.hpp
index 4b36ffc0d8..999f1c3d6c 100644
--- a/boost/utility/string_ref.hpp
+++ b/boost/utility/string_ref.hpp
@@ -1,5 +1,6 @@
/*
Copyright (c) Marshall Clow 2012-2015.
+ Copyright (c) Glen Joseph Fernandes 2019 (glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -17,6 +18,7 @@
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
+#include <boost/utility/ostream_string.hpp>
#include <boost/utility/string_ref_fwd.hpp>
#include <boost/throw_exception.hpp>
@@ -421,52 +423,11 @@ namespace boost {
return basic_string_ref<charT, traits>(x) >= y;
}
- namespace detail {
-
- template<class charT, class traits>
- inline void sr_insert_fill_chars(std::basic_ostream<charT, traits>& os, std::size_t n) {
- enum { chunk_size = 8 };
- charT fill_chars[chunk_size];
- std::fill_n(fill_chars, static_cast< std::size_t >(chunk_size), os.fill());
- for (; n >= chunk_size && os.good(); n -= chunk_size)
- os.write(fill_chars, static_cast< std::size_t >(chunk_size));
- if (n > 0 && os.good())
- os.write(fill_chars, n);
- }
-
- template<class charT, class traits>
- void sr_insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
- const std::size_t size = str.size();
- const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size;
- const bool align_left = (os.flags() & std::basic_ostream<charT, traits>::adjustfield) == std::basic_ostream<charT, traits>::left;
- if (!align_left) {
- detail::sr_insert_fill_chars(os, alignment_size);
- if (os.good())
- os.write(str.data(), size);
- }
- else {
- os.write(str.data(), size);
- if (os.good())
- detail::sr_insert_fill_chars(os, alignment_size);
- }
- }
-
- } // namespace detail
-
// Inserter
template<class charT, class traits>
inline std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
- if (os.good()) {
- const std::size_t size = str.size();
- const std::size_t w = static_cast< std::size_t >(os.width());
- if (w <= size)
- os.write(str.data(), size);
- else
- detail::sr_insert_aligned(os, str);
- os.width(0);
- }
- return os;
+ return boost::ostream_string(os, str.data(), str.size());
}
#if 0
diff --git a/boost/utility/string_view.hpp b/boost/utility/string_view.hpp
index 11aa801e29..ba4ef9308f 100644
--- a/boost/utility/string_view.hpp
+++ b/boost/utility/string_view.hpp
@@ -1,6 +1,7 @@
/*
Copyright (c) Marshall Clow 2012-2015.
Copyright (c) Beman Dawes 2015
+ Copyright (c) Glen Joseph Fernandes 2019 (glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -19,6 +20,7 @@
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
+#include <boost/utility/ostream_string.hpp>
#include <boost/utility/string_view_fwd.hpp>
#include <boost/throw_exception.hpp>
#include <boost/container_hash/hash_fwd.hpp>
@@ -184,7 +186,7 @@ namespace boost {
if (pos > size())
BOOST_THROW_EXCEPTION(std::out_of_range("string_view::copy" ));
size_type rlen = (std::min)(n, len_ - pos);
- traits_type::copy(s, data() + pos, rlen);
+ traits_type::copy(s, data() + pos, rlen);
return rlen;
}
@@ -571,53 +573,12 @@ namespace boost {
return basic_string_view<charT, traits>(x) >= y;
}
- namespace detail {
-
- template<class charT, class traits>
- inline void sv_insert_fill_chars(std::basic_ostream<charT, traits>& os, std::size_t n) {
- enum { chunk_size = 8 };
- charT fill_chars[chunk_size];
- std::fill_n(fill_chars, static_cast< std::size_t >(chunk_size), os.fill());
- for (; n >= chunk_size && os.good(); n -= chunk_size)
- os.write(fill_chars, static_cast< std::size_t >(chunk_size));
- if (n > 0 && os.good())
- os.write(fill_chars, n);
- }
-
- template<class charT, class traits>
- void sv_insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_view<charT,traits>& str) {
- const std::size_t size = str.size();
- const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size;
- const bool align_left = (os.flags() & std::basic_ostream<charT, traits>::adjustfield) == std::basic_ostream<charT, traits>::left;
- if (!align_left) {
- detail::sv_insert_fill_chars(os, alignment_size);
- if (os.good())
- os.write(str.data(), size);
- }
- else {
- os.write(str.data(), size);
- if (os.good())
- detail::sv_insert_fill_chars(os, alignment_size);
- }
- }
-
- } // namespace detail
-
// Inserter
template<class charT, class traits>
inline std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const basic_string_view<charT,traits>& str) {
- if (os.good()) {
- const std::size_t size = str.size();
- const std::size_t w = static_cast< std::size_t >(os.width());
- if (w <= size)
- os.write(str.data(), size);
- else
- detail::sv_insert_aligned(os, str);
- os.width(0);
- }
- return os;
+ return boost::ostream_string(os, str.data(), str.size());
}
#if 0
diff --git a/boost/uuid/basic_name_generator.hpp b/boost/uuid/basic_name_generator.hpp
index 791f48ef7c..746904693f 100644
--- a/boost/uuid/basic_name_generator.hpp
+++ b/boost/uuid/basic_name_generator.hpp
@@ -5,7 +5,7 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UUID_BASIC_NAME_GENERATOR_HPP
#define BOOST_UUID_BASIC_NAME_GENERATOR_HPP
diff --git a/boost/uuid/detail/config.hpp b/boost/uuid/detail/config.hpp
index 602d4ab6af..8cd7b7d7b6 100644
--- a/boost/uuid/detail/config.hpp
+++ b/boost/uuid/detail/config.hpp
@@ -2,7 +2,7 @@
* Copyright Andrey Semashev 2013.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
+ * https://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file uuid/detail/config.hpp
diff --git a/boost/uuid/detail/md5.hpp b/boost/uuid/detail/md5.hpp
index 96d4695a69..1dbdb77f3d 100644
--- a/boost/uuid/detail/md5.hpp
+++ b/boost/uuid/detail/md5.hpp
@@ -21,7 +21,7 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UUID_MD5_HPP
#define BOOST_UUID_MD5_HPP
@@ -30,6 +30,7 @@
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/uuid/uuid.hpp> // for version
+#include <boost/predef/other/endian.h>
#include <string.h>
namespace boost {
@@ -287,12 +288,50 @@ private:
memcpy(ctx->buffer, data, size);
}
+ // This must remain consistent no matter the endianness
#define BOOST_UUID_DETAIL_MD5_OUT(dst, src) \
(dst)[0] = (unsigned char)(src); \
(dst)[1] = (unsigned char)((src) >> 8); \
(dst)[2] = (unsigned char)((src) >> 16); \
(dst)[3] = (unsigned char)((src) >> 24);
+ //
+ // A big-endian issue with MD5 results was resolved
+ // in boost 1.71. If you generated md5 name-based uuids
+ // with boost 1.66 through 1.70 and stored them, then
+ // set the following compatibility flag to ensure that
+ // your hash generation remains consistent.
+ //
+#if defined(BOOST_UUID_COMPAT_PRE_1_71_MD5)
+ #define BOOST_UUID_DETAIL_MD5_BYTE_OUT(dst, src) \
+ BOOST_UUID_DETAIL_MD5_OUT(dst, src)
+#else
+ //
+ // We're copying into a byte buffer which is actually
+ // backed by an unsigned int array, which later on
+ // is then swabbed one more time by the basic name
+ // generator. Therefore the logic here is reversed.
+ // This was done to minimize the impact to existing
+ // name-based hash generation. The correct fix would
+ // be to make this and name generation endian-correct
+ // but that would even break previously generated sha1
+ // hashes too.
+ //
+#if BOOST_ENDIAN_LITTLE_BYTE
+ #define BOOST_UUID_DETAIL_MD5_BYTE_OUT(dst, src) \
+ (dst)[0] = (unsigned char)((src) >> 24); \
+ (dst)[1] = (unsigned char)((src) >> 16); \
+ (dst)[2] = (unsigned char)((src) >> 8); \
+ (dst)[3] = (unsigned char)(src);
+#else
+ #define BOOST_UUID_DETAIL_MD5_BYTE_OUT(dst, src) \
+ (dst)[0] = (unsigned char)(src); \
+ (dst)[1] = (unsigned char)((src) >> 8); \
+ (dst)[2] = (unsigned char)((src) >> 16); \
+ (dst)[3] = (unsigned char)((src) >> 24);
+#endif
+#endif // BOOST_UUID_COMPAT_PRE_1_71_MD5
+
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
{
unsigned long used, available;
@@ -318,10 +357,10 @@ private:
body(ctx, ctx->buffer, 64);
- BOOST_UUID_DETAIL_MD5_OUT(&result[0], ctx->a)
- BOOST_UUID_DETAIL_MD5_OUT(&result[4], ctx->b)
- BOOST_UUID_DETAIL_MD5_OUT(&result[8], ctx->c)
- BOOST_UUID_DETAIL_MD5_OUT(&result[12], ctx->d)
+ BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[0], ctx->a)
+ BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[4], ctx->b)
+ BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[8], ctx->c)
+ BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[12], ctx->d)
memset(ctx, 0, sizeof(*ctx));
}
diff --git a/boost/uuid/detail/random_provider.hpp b/boost/uuid/detail/random_provider.hpp
index bc8a1a4839..bf8e0bee36 100644
--- a/boost/uuid/detail/random_provider.hpp
+++ b/boost/uuid/detail/random_provider.hpp
@@ -3,7 +3,7 @@
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENCE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
//
// Platform-specific random entropy provider
//
diff --git a/boost/uuid/detail/random_provider_arc4random.ipp b/boost/uuid/detail/random_provider_arc4random.ipp
index 6faa94d1f1..bb25f03583 100644
--- a/boost/uuid/detail/random_provider_arc4random.ipp
+++ b/boost/uuid/detail/random_provider_arc4random.ipp
@@ -3,7 +3,7 @@
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENCE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
//
// "A Replacement Call for Random"
// https://man.openbsd.org/arc4random.3
diff --git a/boost/uuid/detail/random_provider_bcrypt.ipp b/boost/uuid/detail/random_provider_bcrypt.ipp
index 623905cbc8..d6d4a3523d 100644
--- a/boost/uuid/detail/random_provider_bcrypt.ipp
+++ b/boost/uuid/detail/random_provider_bcrypt.ipp
@@ -3,7 +3,7 @@
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENCE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
//
// BCrypt provider for entropy
//
@@ -19,9 +19,13 @@
#if defined(BOOST_UUID_FORCE_AUTO_LINK) || (!defined(BOOST_ALL_NO_LIB) && !defined(BOOST_UUID_RANDOM_PROVIDER_NO_LIB))
# define BOOST_LIB_NAME "bcrypt"
-# define BOOST_AUTO_LINK_NOMANGLE
-# include <boost/config/auto_link.hpp>
-# undef BOOST_AUTO_LINK_NOMANGLE
+# if defined(BOOST_AUTO_LINK_NOMANGLE)
+# include <boost/config/auto_link.hpp>
+# else
+# define BOOST_AUTO_LINK_NOMANGLE
+# include <boost/config/auto_link.hpp>
+# undef BOOST_AUTO_LINK_NOMANGLE
+# endif
#endif
namespace boost {
diff --git a/boost/uuid/detail/random_provider_detect_platform.hpp b/boost/uuid/detail/random_provider_detect_platform.hpp
index b3b2655587..014c83be62 100644
--- a/boost/uuid/detail/random_provider_detect_platform.hpp
+++ b/boost/uuid/detail/random_provider_detect_platform.hpp
@@ -3,7 +3,7 @@
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENCE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
//
// Platform-specific random entropy provider platform detection
//
@@ -25,6 +25,12 @@
#endif // defined(SYS_getrandom)
#endif
+// On Linux, getentropy is implemented via getrandom. If we know that getrandom is not supported by the kernel, getentropy
+// will certainly not work, even if libc provides a wrapper function for it. There is no reason, ever, to use getentropy on that platform.
+#if !defined(BOOST_UUID_RANDOM_PROVIDER_DISABLE_GETENTROPY) && (defined(__linux__) || defined(__linux) || defined(linux) || defined(__ANDROID__))
+#define BOOST_UUID_RANDOM_PROVIDER_DISABLE_GETENTROPY
+#endif
+
//
// Platform Detection - will load in the correct header and
// will define the class <tt>random_provider_base</tt>.
@@ -54,7 +60,7 @@
# define BOOST_UUID_RANDOM_PROVIDER_GETRANDOM
# define BOOST_UUID_RANDOM_PROVIDER_NAME getrandom
-#elif BOOST_LIB_C_GNU >= BOOST_VERSION_NUMBER(2, 25, 0) && !defined(BOOST_UUID_RANDOM_PROVIDER_FORCE_POSIX)
+#elif BOOST_LIB_C_GNU >= BOOST_VERSION_NUMBER(2, 25, 0) && !defined(BOOST_UUID_RANDOM_PROVIDER_FORCE_POSIX) && !defined(BOOST_UUID_RANDOM_PROVIDER_DISABLE_GETENTROPY)
# define BOOST_UUID_RANDOM_PROVIDER_GETENTROPY
# define BOOST_UUID_RANDOM_PROVIDER_NAME getentropy
diff --git a/boost/uuid/detail/random_provider_getentropy.ipp b/boost/uuid/detail/random_provider_getentropy.ipp
index 4124854597..c0144999e4 100644
--- a/boost/uuid/detail/random_provider_getentropy.ipp
+++ b/boost/uuid/detail/random_provider_getentropy.ipp
@@ -3,7 +3,7 @@
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENCE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
//
// getentropy() capable platforms
//
diff --git a/boost/uuid/detail/random_provider_getrandom.ipp b/boost/uuid/detail/random_provider_getrandom.ipp
index 8c7fdbfb71..036cd4040f 100644
--- a/boost/uuid/detail/random_provider_getrandom.ipp
+++ b/boost/uuid/detail/random_provider_getrandom.ipp
@@ -3,7 +3,7 @@
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENCE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
//
// getrandom() capable platforms
//
diff --git a/boost/uuid/detail/random_provider_include_platform.hpp b/boost/uuid/detail/random_provider_include_platform.hpp
index 192c2bfd60..7b99b80c3a 100644
--- a/boost/uuid/detail/random_provider_include_platform.hpp
+++ b/boost/uuid/detail/random_provider_include_platform.hpp
@@ -3,7 +3,7 @@
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENCE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
//
// Platform-specific random entropy provider platform definition
//
diff --git a/boost/uuid/detail/random_provider_posix.ipp b/boost/uuid/detail/random_provider_posix.ipp
index 723394df27..4a22235a58 100644
--- a/boost/uuid/detail/random_provider_posix.ipp
+++ b/boost/uuid/detail/random_provider_posix.ipp
@@ -7,7 +7,7 @@
*
* Distributed under the Boost Software License, Version 1.0. (See
* accompanying file LICENSE_1_0.txt or copy at
-* http://www.boost.org/LICENSE_1_0.txt)
+* https://www.boost.org/LICENSE_1_0.txt)
*
* $Id$
*/
diff --git a/boost/uuid/detail/random_provider_wincrypt.ipp b/boost/uuid/detail/random_provider_wincrypt.ipp
index d8409ea246..099f70cb5e 100644
--- a/boost/uuid/detail/random_provider_wincrypt.ipp
+++ b/boost/uuid/detail/random_provider_wincrypt.ipp
@@ -7,7 +7,7 @@
*
* Distributed under the Boost Software License, Version 1.0. (See
* accompanying file LICENSE_1_0.txt or copy at
-* http://www.boost.org/LICENSE_1_0.txt)
+* https://www.boost.org/LICENSE_1_0.txt)
*
* $Id$
*/
@@ -27,9 +27,13 @@
# else
# define BOOST_LIB_NAME "advapi32"
# endif
-# define BOOST_AUTO_LINK_NOMANGLE
-# include <boost/config/auto_link.hpp>
-# undef BOOST_AUTO_LINK_NOMANGLE
+# if defined(BOOST_AUTO_LINK_NOMANGLE)
+# include <boost/config/auto_link.hpp>
+# else
+# define BOOST_AUTO_LINK_NOMANGLE
+# include <boost/config/auto_link.hpp>
+# undef BOOST_AUTO_LINK_NOMANGLE
+# endif
#endif
namespace boost {
diff --git a/boost/uuid/detail/sha1.hpp b/boost/uuid/detail/sha1.hpp
index 871a3199d6..47f858a342 100644
--- a/boost/uuid/detail/sha1.hpp
+++ b/boost/uuid/detail/sha1.hpp
@@ -1,7 +1,7 @@
// Copyright 2007 Andy Tompkins.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
// Revision History
// 29 May 2007 - Initial Revision
@@ -186,7 +186,7 @@ inline void sha1::process_block()
inline unsigned char sha1::get_version() const
{
// RFC 4122 Section 4.1.3
- return uuid::version_name_based_sha1;
+ return uuid::version_name_based_sha1;
}
inline void sha1::get_digest(digest_type& digest)
diff --git a/boost/uuid/detail/uuid_generic.ipp b/boost/uuid/detail/uuid_generic.ipp
index 07c5cf4033..e473f2ef44 100644
--- a/boost/uuid/detail/uuid_generic.ipp
+++ b/boost/uuid/detail/uuid_generic.ipp
@@ -2,7 +2,7 @@
* Copyright Andy Tompkins 2006.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
+ * https://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file uuid/detail/uuid_generic.ipp
diff --git a/boost/uuid/detail/uuid_x86.ipp b/boost/uuid/detail/uuid_x86.ipp
index 0ccddef88b..ecbf9a5d17 100644
--- a/boost/uuid/detail/uuid_x86.ipp
+++ b/boost/uuid/detail/uuid_x86.ipp
@@ -2,7 +2,7 @@
* Copyright Andrey Semashev 2013.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
+ * https://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file uuid/detail/uuid_x86.ipp
diff --git a/boost/uuid/entropy_error.hpp b/boost/uuid/entropy_error.hpp
index e7a48b88b9..27a7078b01 100644
--- a/boost/uuid/entropy_error.hpp
+++ b/boost/uuid/entropy_error.hpp
@@ -3,7 +3,7 @@
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENCE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
//
// Entropy error class
//
diff --git a/boost/uuid/name_generator.hpp b/boost/uuid/name_generator.hpp
index ead8174d1c..4aab7fdad4 100644
--- a/boost/uuid/name_generator.hpp
+++ b/boost/uuid/name_generator.hpp
@@ -5,7 +5,7 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UUID_NAME_GENERATOR_HPP
#define BOOST_UUID_NAME_GENERATOR_HPP
diff --git a/boost/uuid/name_generator_md5.hpp b/boost/uuid/name_generator_md5.hpp
index 7b13698df2..6462b452b6 100644
--- a/boost/uuid/name_generator_md5.hpp
+++ b/boost/uuid/name_generator_md5.hpp
@@ -4,7 +4,7 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UUID_NAME_GENERATOR_MD5_HPP
#define BOOST_UUID_NAME_GENERATOR_MD5_HPP
diff --git a/boost/uuid/name_generator_sha1.hpp b/boost/uuid/name_generator_sha1.hpp
index c34425f5b0..722e79af6a 100644
--- a/boost/uuid/name_generator_sha1.hpp
+++ b/boost/uuid/name_generator_sha1.hpp
@@ -5,7 +5,7 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UUID_NAME_GENERATOR_SHA1_HPP
#define BOOST_UUID_NAME_GENERATOR_SHA1_HPP
diff --git a/boost/uuid/nil_generator.hpp b/boost/uuid/nil_generator.hpp
index c3c5818376..4c298192ee 100644
--- a/boost/uuid/nil_generator.hpp
+++ b/boost/uuid/nil_generator.hpp
@@ -3,7 +3,7 @@
// Copyright 2010 Andy Tompkins.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UUID_NIL_GENERATOR_HPP
#define BOOST_UUID_NIL_GENERATOR_HPP
diff --git a/boost/uuid/random_generator.hpp b/boost/uuid/random_generator.hpp
index 46b941bcce..0fa34c0453 100644
--- a/boost/uuid/random_generator.hpp
+++ b/boost/uuid/random_generator.hpp
@@ -4,7 +4,7 @@
// Copyright 2017 James E. King III
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UUID_RANDOM_GENERATOR_HPP
#define BOOST_UUID_RANDOM_GENERATOR_HPP
diff --git a/boost/uuid/string_generator.hpp b/boost/uuid/string_generator.hpp
index 1903448623..7d9597edaf 100644
--- a/boost/uuid/string_generator.hpp
+++ b/boost/uuid/string_generator.hpp
@@ -3,7 +3,7 @@
// Copyright 2010 Andy Tompkins.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UUID_STRING_GENERATOR_HPP
#define BOOST_UUID_STRING_GENERATOR_HPP
diff --git a/boost/uuid/uuid.hpp b/boost/uuid/uuid.hpp
index e542d91b20..d3bb34b72e 100644
--- a/boost/uuid/uuid.hpp
+++ b/boost/uuid/uuid.hpp
@@ -3,7 +3,7 @@
// Copyright 2006 Andy Tompkins.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
// Revision History
// 06 Feb 2006 - Initial Revision
diff --git a/boost/uuid/uuid_generators.hpp b/boost/uuid/uuid_generators.hpp
index 29d39ccf65..2916e69a01 100644
--- a/boost/uuid/uuid_generators.hpp
+++ b/boost/uuid/uuid_generators.hpp
@@ -3,7 +3,7 @@
// Copyright 2006 Andy Tompkins.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
// Revision History
// 06 Feb 2006 - Initial Revision
diff --git a/boost/uuid/uuid_hash.hpp b/boost/uuid/uuid_hash.hpp
index a154871b3f..8fe56bc4cf 100644
--- a/boost/uuid/uuid_hash.hpp
+++ b/boost/uuid/uuid_hash.hpp
@@ -3,7 +3,7 @@
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENCE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
//
// std::hash support for uuid
//
@@ -13,7 +13,7 @@
#include <boost/config.hpp>
#include <boost/container_hash/hash.hpp>
-#include <boost/uuid/uuid_io.hpp>
+#include <boost/uuid/uuid.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -31,7 +31,7 @@ namespace std
{
std::size_t operator () (const boost::uuids::uuid& value) const BOOST_NOEXCEPT
{
- return boost::hash_value(to_string(value));
+ return boost::uuids::hash_value(value);
}
};
}
diff --git a/boost/uuid/uuid_io.hpp b/boost/uuid/uuid_io.hpp
index e92e88131b..11bd4a2350 100644
--- a/boost/uuid/uuid_io.hpp
+++ b/boost/uuid/uuid_io.hpp
@@ -3,7 +3,7 @@
// Copyright 2009 Andy Tompkins.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
// Revision History
// 20 Mar 2009 - Initial Revision
diff --git a/boost/uuid/uuid_serialize.hpp b/boost/uuid/uuid_serialize.hpp
index 3d8a608b18..31312cf01c 100644
--- a/boost/uuid/uuid_serialize.hpp
+++ b/boost/uuid/uuid_serialize.hpp
@@ -3,7 +3,7 @@
// Copyright 2007 Andy Tompkins.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// https://www.boost.org/LICENSE_1_0.txt)
// Revision History
// 12 Nov 2007 - Initial Revision
diff --git a/boost/variant/detail/apply_visitor_unary.hpp b/boost/variant/detail/apply_visitor_unary.hpp
index 71610cb674..c3a741efcc 100644
--- a/boost/variant/detail/apply_visitor_unary.hpp
+++ b/boost/variant/detail/apply_visitor_unary.hpp
@@ -23,6 +23,7 @@
# include <boost/mpl/size.hpp>
# include <boost/utility/declval.hpp>
# include <boost/core/enable_if.hpp>
+# include <boost/type_traits/copy_cv_ref.hpp>
# include <boost/type_traits/remove_reference.hpp>
# include <boost/variant/detail/has_result_type.hpp>
#endif
@@ -85,7 +86,7 @@ namespace detail { namespace variant {
// This class serves only metaprogramming purposes. none of its methods must be called at runtime!
template <class Visitor, class Variant>
struct result_multideduce1 {
- typedef typename Variant::types types;
+ typedef typename remove_reference<Variant>::type::types types;
typedef typename boost::mpl::begin<types>::type begin_it;
typedef typename boost::mpl::advance<
begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
@@ -95,14 +96,14 @@ struct result_multideduce1 {
struct deduce_impl {
typedef typename boost::mpl::next<It>::type next_t;
typedef typename boost::mpl::deref<It>::type value_t;
- typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< value_t >() )
+ typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )
: boost::declval< typename deduce_impl<next_t>::type >()) type;
};
template <class Dummy>
struct deduce_impl<last_it, Dummy> {
typedef typename boost::mpl::deref<last_it>::type value_t;
- typedef decltype(boost::declval< Visitor& >()( boost::declval< value_t >() )) type;
+ typedef decltype(boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )) type;
};
typedef typename deduce_impl<begin_it>::type type;
@@ -132,7 +133,7 @@ inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable,
boost::detail::variant::has_result_type<Visitor>
>::type* = 0)
{
- boost::detail::variant::result_wrapper1<Visitor, typename remove_reference<Visitable>::type> cpp14_vis(::boost::forward<Visitor>(visitor));
+ boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(::boost::forward<Visitor>(visitor));
return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
}
diff --git a/boost/variant/detail/forced_return.hpp b/boost/variant/detail/forced_return.hpp
index 52360fe0f4..d3d00a9684 100644
--- a/boost/variant/detail/forced_return.hpp
+++ b/boost/variant/detail/forced_return.hpp
@@ -15,7 +15,6 @@
#include <boost/config.hpp>
#include <boost/assert.hpp>
-#include <cstdlib> // std::abort
#ifdef BOOST_MSVC
@@ -25,12 +24,6 @@
namespace boost { namespace detail { namespace variant {
-BOOST_NORETURN inline void forced_return_no_return() { // fixes `must return a value` warnings
- using namespace std;
- abort(); // some implementations have no std::abort
-}
-
-
///////////////////////////////////////////////////////////////////////////////
// (detail) function template forced_return
//
@@ -44,12 +37,9 @@ forced_return()
// logical error: should never be here! (see above)
BOOST_ASSERT(false);
- forced_return_no_return();
-
-#ifdef BOOST_NO_NORETURN
T (*dummy)() = 0;
- return dummy();
-#endif
+ (void)dummy;
+ BOOST_UNREACHABLE_RETURN(dummy());
}
}}} // namespace boost::detail::variant
diff --git a/boost/variant/detail/std_hash.hpp b/boost/variant/detail/std_hash.hpp
new file mode 100644
index 0000000000..6da4e29437
--- /dev/null
+++ b/boost/variant/detail/std_hash.hpp
@@ -0,0 +1,46 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/std_hash.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2018-2019 Antony Polukhin
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_VARIANT_DETAIL_STD_HASH_HPP
+#define BOOST_VARIANT_DETAIL_STD_HASH_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/variant/variant_fwd.hpp>
+#include <boost/variant/detail/hash_variant.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH
+//
+// Define this macro if you do not with to have a std::hash specialization for
+// boost::variant.
+
+#if !defined(BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
+
+#include <functional> // for std::hash
+
+namespace std {
+ template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
+ struct hash<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) > > {
+ std::size_t operator()(const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& val) const {
+ return ::boost::hash_value(val);
+ }
+ };
+}
+
+#endif // #if !defined(BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
+
+#endif // BOOST_VARIANT_DETAIL_STD_HASH_HPP
+
diff --git a/boost/variant/detail/visitation_impl.hpp b/boost/variant/detail/visitation_impl.hpp
index c7250c3025..69b7a2b4ff 100644
--- a/boost/variant/detail/visitation_impl.hpp
+++ b/boost/variant/detail/visitation_impl.hpp
@@ -190,7 +190,7 @@ template <
, typename Visitor, typename VoidPtrCV
, typename NoBackupFlag
>
-inline typename Visitor::result_type
+BOOST_FORCEINLINE typename Visitor::result_type
visitation_impl(
const int internal_which, const int logical_which
, Visitor& visitor, VoidPtrCV storage
diff --git a/boost/variant/variant.hpp b/boost/variant/variant.hpp
index 21ada025f8..8be5a6da38 100644
--- a/boost/variant/variant.hpp
+++ b/boost/variant/variant.hpp
@@ -32,6 +32,7 @@
#include <boost/variant/detail/over_sequence.hpp>
#include <boost/variant/detail/visitation_impl.hpp>
#include <boost/variant/detail/hash_variant.hpp>
+#include <boost/variant/detail/std_hash.hpp>
#include <boost/variant/detail/move.hpp>
@@ -2314,7 +2315,7 @@ public:
#endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename Visitor, typename VoidPtrCV>
- static typename Visitor::result_type
+ BOOST_FORCEINLINE static typename Visitor::result_type
internal_apply_visitor_impl(
int internal_which
, int logical_which
@@ -2339,7 +2340,7 @@ public:
}
template <typename Visitor>
- typename Visitor::result_type
+ BOOST_FORCEINLINE typename Visitor::result_type
internal_apply_visitor(Visitor& visitor)
{
return internal_apply_visitor_impl(
@@ -2348,7 +2349,7 @@ public:
}
template <typename Visitor>
- typename Visitor::result_type
+ BOOST_FORCEINLINE typename Visitor::result_type
internal_apply_visitor(Visitor& visitor) const
{
return internal_apply_visitor_impl(
diff --git a/boost/variant2/variant.hpp b/boost/variant2/variant.hpp
new file mode 100644
index 0000000000..d661ca5c53
--- /dev/null
+++ b/boost/variant2/variant.hpp
@@ -0,0 +1,1795 @@
+#ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED
+#define BOOST_VARIANT2_VARIANT_HPP_INCLUDED
+
+// Copyright 2017-2019 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#if defined(_MSC_VER) && _MSC_VER < 1910
+# pragma warning( push )
+# pragma warning( disable: 4521 4522 ) // multiple copy operators
+#endif
+
+#ifndef BOOST_MP11_HPP_INCLUDED
+#include <boost/mp11.hpp>
+#endif
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <cstddef>
+#include <type_traits>
+#include <exception>
+#include <cassert>
+#include <initializer_list>
+#include <utility>
+
+//
+
+namespace boost
+{
+
+#ifdef BOOST_NO_EXCEPTIONS
+
+BOOST_NORETURN void throw_exception( std::exception const & e ); // user defined
+
+#endif
+
+namespace variant2
+{
+
+// bad_variant_access
+
+class bad_variant_access: public std::exception
+{
+public:
+
+ bad_variant_access() noexcept
+ {
+ }
+
+ char const * what() const noexcept
+ {
+ return "bad_variant_access";
+ }
+};
+
+namespace detail
+{
+
+BOOST_NORETURN inline void throw_bad_variant_access()
+{
+#ifdef BOOST_NO_EXCEPTIONS
+
+ boost::throw_exception( bad_variant_access() );
+
+#else
+
+ throw bad_variant_access();
+
+#endif
+}
+
+} // namespace detail
+
+// monostate
+
+struct monostate
+{
+};
+
+constexpr bool operator<(monostate, monostate) noexcept { return false; }
+constexpr bool operator>(monostate, monostate) noexcept { return false; }
+constexpr bool operator<=(monostate, monostate) noexcept { return true; }
+constexpr bool operator>=(monostate, monostate) noexcept { return true; }
+constexpr bool operator==(monostate, monostate) noexcept { return true; }
+constexpr bool operator!=(monostate, monostate) noexcept { return false; }
+
+// variant forward declaration
+
+template<class... T> class variant;
+
+// variant_size
+
+template<class T> struct variant_size
+{
+};
+
+template<class T> struct variant_size<T const>: variant_size<T>
+{
+};
+
+template<class T> struct variant_size<T volatile>: variant_size<T>
+{
+};
+
+template<class T> struct variant_size<T const volatile>: variant_size<T>
+{
+};
+
+template<class T> struct variant_size<T&>: variant_size<T>
+{
+};
+
+template<class T> struct variant_size<T&&>: variant_size<T>
+{
+};
+
+#if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
+
+template <class T> /*inline*/ constexpr std::size_t variant_size_v = variant_size<T>::value;
+
+#endif
+
+template <class... T> struct variant_size<variant<T...>>: mp11::mp_size<variant<T...>>
+{
+};
+
+// variant_alternative
+
+template<std::size_t I, class T> struct variant_alternative;
+
+template<std::size_t I, class T> using variant_alternative_t = typename variant_alternative<I, T>::type;
+
+#if BOOST_WORKAROUND(BOOST_GCC, < 40900)
+
+namespace detail
+{
+
+template<std::size_t I, class T, bool E> struct variant_alternative_impl
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...>, true>
+{
+ using type = mp11::mp_at_c<variant<T...>, I>;
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const, true>: std::add_const< mp11::mp_at_c<variant<T...>, I> >
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> volatile, true>: std::add_volatile< mp11::mp_at_c<variant<T...>, I> >
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const volatile, true>: std::add_cv< mp11::mp_at_c<variant<T...>, I> >
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...>&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> >
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> const >
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> volatile&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> volatile >
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const volatile&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> const volatile >
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...>&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> >
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> const >
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> volatile&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> volatile >
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const volatile&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> const volatile >
+{
+};
+
+} // namespace detail
+
+template<std::size_t I, class T> struct variant_alternative
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>>: public detail::variant_alternative_impl<I, variant<T...>, (I < sizeof...(T))>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const>: public detail::variant_alternative_impl<I, variant<T...> const, (I < sizeof...(T))>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> volatile>: public detail::variant_alternative_impl<I, variant<T...> volatile, (I < sizeof...(T))>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const volatile>: public detail::variant_alternative_impl<I, variant<T...> const volatile, (I < sizeof...(T))>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>&>: public detail::variant_alternative_impl<I, variant<T...>&, (I < sizeof...(T))>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const&>: public detail::variant_alternative_impl<I, variant<T...> const&, (I < sizeof...(T))>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> volatile&>: public detail::variant_alternative_impl<I, variant<T...> volatile&, (I < sizeof...(T))>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const volatile&>: public detail::variant_alternative_impl<I, variant<T...> const volatile&, (I < sizeof...(T))>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>&&>: public detail::variant_alternative_impl<I, variant<T...>&&, (I < sizeof...(T))>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const&&>: public detail::variant_alternative_impl<I, variant<T...> const&&, (I < sizeof...(T))>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> volatile&&>: public detail::variant_alternative_impl<I, variant<T...> volatile&&, (I < sizeof...(T))>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const volatile&&>: public detail::variant_alternative_impl<I, variant<T...> const volatile&&, (I < sizeof...(T))>
+{
+};
+
+#else
+
+namespace detail
+{
+
+#if defined( BOOST_MP11_VERSION ) && BOOST_MP11_VERSION >= 107000
+
+template<class I, class T, class Q> using var_alt_impl = mp11::mp_invoke_q<Q, variant_alternative_t<I::value, T>>;
+
+#else
+
+template<class I, class T, class Q> using var_alt_impl = mp11::mp_invoke<Q, variant_alternative_t<I::value, T>>;
+
+#endif
+
+} // namespace detail
+
+template<std::size_t I, class T> struct variant_alternative
+{
+};
+
+template<std::size_t I, class T> struct variant_alternative<I, T const>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_const>>
+{
+};
+
+template<std::size_t I, class T> struct variant_alternative<I, T volatile>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_volatile>>
+{
+};
+
+template<std::size_t I, class T> struct variant_alternative<I, T const volatile>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_cv>>
+{
+};
+
+template<std::size_t I, class T> struct variant_alternative<I, T&>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_lvalue_reference>>
+{
+};
+
+template<std::size_t I, class T> struct variant_alternative<I, T&&>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_rvalue_reference>>
+{
+};
+
+template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>>: mp11::mp_defer<mp11::mp_at, variant<T...>, mp11::mp_size_t<I>>
+{
+};
+
+#endif
+
+// variant_npos
+
+constexpr std::size_t variant_npos = ~static_cast<std::size_t>( 0 );
+
+// holds_alternative
+
+template<class U, class... T> constexpr bool holds_alternative( variant<T...> const& v ) noexcept
+{
+ static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
+ return v.index() == mp11::mp_find<variant<T...>, U>::value;
+}
+
+// get (index)
+
+template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>& get(variant<T...>& v)
+{
+ static_assert( I < sizeof...(T), "Index out of bounds" );
+ return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( mp11::mp_size_t<I>() );
+}
+
+template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>&& get(variant<T...>&& v)
+{
+ static_assert( I < sizeof...(T), "Index out of bounds" );
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
+
+ return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( mp11::mp_size_t<I>() ) );
+
+#else
+
+ if( v.index() != I ) detail::throw_bad_variant_access();
+ return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
+
+#endif
+}
+
+template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const& get(variant<T...> const& v)
+{
+ static_assert( I < sizeof...(T), "Index out of bounds" );
+ return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( mp11::mp_size_t<I>() );
+}
+
+template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const&& get(variant<T...> const&& v)
+{
+ static_assert( I < sizeof...(T), "Index out of bounds" );
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
+
+ return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( mp11::mp_size_t<I>() ) );
+
+#else
+
+ if( v.index() != I ) detail::throw_bad_variant_access();
+ return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
+
+#endif
+}
+
+// detail::unsafe_get (for visit)
+
+namespace detail
+{
+
+template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>& unsafe_get(variant<T...>& v)
+{
+ static_assert( I < sizeof...(T), "Index out of bounds" );
+ return v._get_impl( mp11::mp_size_t<I>() );
+}
+
+template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>&& unsafe_get(variant<T...>&& v)
+{
+ static_assert( I < sizeof...(T), "Index out of bounds" );
+ return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
+}
+
+template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const& unsafe_get(variant<T...> const& v)
+{
+ static_assert( I < sizeof...(T), "Index out of bounds" );
+ return v._get_impl( mp11::mp_size_t<I>() );
+}
+
+template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const&& unsafe_get(variant<T...> const&& v)
+{
+ static_assert( I < sizeof...(T), "Index out of bounds" );
+ return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
+}
+
+} // namespace detail
+
+// get (type)
+
+template<class U, class... T> constexpr U& get(variant<T...>& v)
+{
+ static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
+
+ using I = mp11::mp_find<variant<T...>, U>;
+
+ return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( I() );
+}
+
+template<class U, class... T> constexpr U&& get(variant<T...>&& v)
+{
+ static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
+
+ using I = mp11::mp_find<variant<T...>, U>;
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
+
+ return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( I() ) );
+
+#else
+
+ if( v.index() != I::value ) detail::throw_bad_variant_access();
+ return std::move( v._get_impl( I() ) );
+
+#endif
+}
+
+template<class U, class... T> constexpr U const& get(variant<T...> const& v)
+{
+ static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
+
+ using I = mp11::mp_find<variant<T...>, U>;
+
+ return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( I() );
+}
+
+template<class U, class... T> constexpr U const&& get(variant<T...> const&& v)
+{
+ static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
+
+ using I = mp11::mp_find<variant<T...>, U>;
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
+
+ return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( I() ) );
+
+#else
+
+ if( v.index() != I::value ) detail::throw_bad_variant_access();
+ return std::move( v._get_impl( I() ) );
+
+#endif
+}
+
+// get_if
+
+template<std::size_t I, class... T> constexpr typename std::add_pointer<variant_alternative_t<I, variant<T...>>>::type get_if(variant<T...>* v) noexcept
+{
+ static_assert( I < sizeof...(T), "Index out of bounds" );
+ return v && v->index() == I? &v->_get_impl( mp11::mp_size_t<I>() ): 0;
+}
+
+template<std::size_t I, class... T> constexpr typename std::add_pointer<const variant_alternative_t<I, variant<T...>>>::type get_if(variant<T...> const * v) noexcept
+{
+ static_assert( I < sizeof...(T), "Index out of bounds" );
+ return v && v->index() == I? &v->_get_impl( mp11::mp_size_t<I>() ): 0;
+}
+
+template<class U, class... T> constexpr typename std::add_pointer<U>::type get_if(variant<T...>* v) noexcept
+{
+ static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
+
+ using I = mp11::mp_find<variant<T...>, U>;
+
+ return v && v->index() == I::value? &v->_get_impl( I() ): 0;
+}
+
+template<class U, class... T> constexpr typename std::add_pointer<U const>::type get_if(variant<T...> const * v) noexcept
+{
+ static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
+
+ using I = mp11::mp_find<variant<T...>, U>;
+
+ return v && v->index() == I::value? &v->_get_impl( I() ): 0;
+}
+
+//
+
+namespace detail
+{
+
+// trivially_*
+
+#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000
+
+template<class T> struct is_trivially_copy_constructible: mp11::mp_bool<std::is_copy_constructible<T>::value && std::has_trivial_copy_constructor<T>::value>
+{
+};
+
+template<class T> struct is_trivially_copy_assignable: mp11::mp_bool<std::is_copy_assignable<T>::value && std::has_trivial_copy_assign<T>::value>
+{
+};
+
+template<class T> struct is_trivially_move_constructible: mp11::mp_bool<std::is_move_constructible<T>::value && std::is_trivial<T>::value>
+{
+};
+
+template<class T> struct is_trivially_move_assignable: mp11::mp_bool<std::is_move_assignable<T>::value && std::is_trivial<T>::value>
+{
+};
+
+#else
+
+using std::is_trivially_copy_constructible;
+using std::is_trivially_copy_assignable;
+using std::is_trivially_move_constructible;
+using std::is_trivially_move_assignable;
+
+#endif
+
+// variant_storage
+
+template<class D, class... T> union variant_storage_impl;
+
+template<class... T> using variant_storage = variant_storage_impl<mp11::mp_all<std::is_trivially_destructible<T>...>, T...>;
+
+template<class D> union variant_storage_impl<D>
+{
+};
+
+// not all trivially destructible
+template<class T1, class... T> union variant_storage_impl<mp11::mp_false, T1, T...>
+{
+ T1 first_;
+ variant_storage<T...> rest_;
+
+ template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
+ {
+ }
+
+ template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
+ {
+ }
+
+ ~variant_storage_impl()
+ {
+ }
+
+ template<class... A> void emplace( mp11::mp_size_t<0>, A&&... a )
+ {
+ ::new( &first_ ) T1( std::forward<A>(a)... );
+ }
+
+ template<std::size_t I, class... A> void emplace( mp11::mp_size_t<I>, A&&... a )
+ {
+ rest_.emplace( mp11::mp_size_t<I-1>(), std::forward<A>(a)... );
+ }
+
+ BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<0> ) noexcept { return first_; }
+ constexpr T1 const& get( mp11::mp_size_t<0> ) const noexcept { return first_; }
+
+ template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-1>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
+ template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-1> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
+};
+
+// all trivially destructible
+template<class T1, class... T> union variant_storage_impl<mp11::mp_true, T1, T...>
+{
+ T1 first_;
+ variant_storage<T...> rest_;
+
+ template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
+ {
+ }
+
+ template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
+ {
+ }
+
+ template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<0>, A&&... a )
+ {
+ ::new( &first_ ) T1( std::forward<A>(a)... );
+ }
+
+ template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, mp11::mp_size_t<I>, A&&... a )
+ {
+ rest_.emplace( mp11::mp_size_t<I-1>(), std::forward<A>(a)... );
+ }
+
+ template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, mp11::mp_size_t<I>, A&&... a )
+ {
+ *this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... );
+ }
+
+ template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( mp11::mp_size_t<I>, A&&... a )
+ {
+ this->emplace_impl( mp11::mp_all<detail::is_trivially_move_assignable<T1>, detail::is_trivially_move_assignable<T>...>(), mp11::mp_size_t<I>(), std::forward<A>(a)... );
+ }
+
+ BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<0> ) noexcept { return first_; }
+ constexpr T1 const& get( mp11::mp_size_t<0> ) const noexcept { return first_; }
+
+ template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-1>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
+ template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-1> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
+};
+
+// resolve_overload_*
+
+template<class... T> struct overload;
+
+template<> struct overload<>
+{
+ void operator()() const;
+};
+
+template<class T1, class... T> struct overload<T1, T...>: overload<T...>
+{
+ using overload<T...>::operator();
+ mp11::mp_identity<T1> operator()(T1) const;
+};
+
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
+
+template<class U, class... T> using resolve_overload_type_ = decltype( overload<T...>()(std::declval<U>()) );
+
+template<class U, class... T> struct resolve_overload_type_impl: mp11::mp_defer< resolve_overload_type_, U, T... >
+{
+};
+
+template<class U, class... T> using resolve_overload_type = typename resolve_overload_type_impl<U, T...>::type::type;
+
+#else
+
+template<class U, class... T> using resolve_overload_type = typename decltype( overload<T...>()(std::declval<U>()) )::type;
+
+#endif
+
+template<class U, class... T> using resolve_overload_index = mp11::mp_find<mp11::mp_list<T...>, resolve_overload_type<U, T...>>;
+
+// variant_base
+
+template<bool is_trivially_destructible, bool is_single_buffered, class... T> struct variant_base_impl;
+template<class... T> using variant_base = variant_base_impl<mp11::mp_all<std::is_trivially_destructible<T>...>::value, mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value, T...>;
+
+struct none {};
+
+// trivially destructible, single buffered
+template<class... T> struct variant_base_impl<true, true, T...>
+{
+ int ix_;
+ variant_storage<none, T...> st1_;
+
+ constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
+ {
+ }
+
+ template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
+ {
+ }
+
+ // requires: ix_ == 0
+ template<class I, class... A> void _replace( I, A&&... a )
+ {
+ ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
+ ix_ = I::value + 1;
+ }
+
+ constexpr std::size_t index() const noexcept
+ {
+ return ix_ - 1;
+ }
+
+ template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
+ {
+ size_t const J = I+1;
+
+ assert( ix_ == J );
+
+ return st1_.get( mp11::mp_size_t<J>() );
+ }
+
+ template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
+ {
+ // size_t const J = I+1;
+ // assert( ix_ == I+1 );
+
+ return st1_.get( mp11::mp_size_t<I+1>() );
+ }
+
+ template<std::size_t J, class U, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, A&&... a )
+ {
+ static_assert( std::is_nothrow_constructible<U, A&&...>::value, "Logic error: U must be nothrow constructible from A&&..." );
+
+ st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
+ ix_ = J;
+ }
+
+ template<std::size_t J, class U, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, A&&... a )
+ {
+ static_assert( std::is_nothrow_move_constructible<U>::value, "Logic error: U must be nothrow move constructible" );
+
+ U tmp( std::forward<A>(a)... );
+
+ st1_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
+ ix_ = J;
+ }
+
+ template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( A&&... a )
+ {
+ std::size_t const J = I+1;
+ using U = mp11::mp_at_c<variant<T...>, I>;
+
+ this->emplace_impl<J, U>( std::is_nothrow_constructible<U, A&&...>(), std::forward<A>(a)... );
+ }
+};
+
+// trivially destructible, double buffered
+template<class... T> struct variant_base_impl<true, false, T...>
+{
+ int ix_;
+ variant_storage<none, T...> st1_;
+ variant_storage<none, T...> st2_;
+
+ constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
+ {
+ }
+
+ template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() )
+ {
+ }
+
+ // requires: ix_ == 0
+ template<class I, class... A> void _replace( I, A&&... a )
+ {
+ ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
+ ix_ = I::value + 1;
+ }
+
+ constexpr std::size_t index() const noexcept
+ {
+ return ix_ >= 0? ix_ - 1: -ix_ - 1;
+ }
+
+ template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
+ {
+ size_t const J = I+1;
+
+ assert( ix_ == J || -ix_ == J );
+
+ constexpr mp11::mp_size_t<J> j{};
+ return ix_ >= 0? st1_.get( j ): st2_.get( j );
+ }
+
+ template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
+ {
+ // size_t const J = I+1;
+ // assert( ix_ == J || -ix_ == J );
+ // constexpr mp_size_t<J> j{};
+
+ return ix_ >= 0? st1_.get( mp11::mp_size_t<I+1>() ): st2_.get( mp11::mp_size_t<I+1>() );
+ }
+
+ template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( A&&... a )
+ {
+ size_t const J = I+1;
+
+ if( ix_ >= 0 )
+ {
+ st2_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
+ ix_ = -static_cast<int>( J );
+ }
+ else
+ {
+ st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
+ ix_ = J;
+ }
+ }
+};
+
+// not trivially destructible, single buffered
+template<class... T> struct variant_base_impl<false, true, T...>
+{
+ int ix_;
+ variant_storage<none, T...> st1_;
+
+ constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
+ {
+ }
+
+ template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
+ {
+ }
+
+ // requires: ix_ == 0
+ template<class I, class... A> void _replace( I, A&&... a )
+ {
+ ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
+ ix_ = I::value + 1;
+ }
+
+ //[&]( auto I ){
+ // using U = mp_at_c<mp_list<none, T...>, I>;
+ // st1_.get( I ).~U();
+ //}
+
+ struct _destroy_L1
+ {
+ variant_base_impl * this_;
+
+ template<class I> void operator()( I ) const noexcept
+ {
+ using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
+ this_->st1_.get( I() ).~U();
+ }
+ };
+
+ void _destroy() noexcept
+ {
+ if( ix_ > 0 )
+ {
+ mp11::mp_with_index<1 + sizeof...(T)>( ix_, _destroy_L1{ this } );
+ }
+ }
+
+ ~variant_base_impl() noexcept
+ {
+ _destroy();
+ }
+
+ constexpr std::size_t index() const noexcept
+ {
+ return ix_ - 1;
+ }
+
+ template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
+ {
+ size_t const J = I+1;
+
+ assert( ix_ == J );
+
+ return st1_.get( mp11::mp_size_t<J>() );
+ }
+
+ template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
+ {
+ // size_t const J = I+1;
+ // assert( ix_ == J );
+
+ return st1_.get( mp11::mp_size_t<I+1>() );
+ }
+
+ template<std::size_t I, class... A> void emplace( A&&... a )
+ {
+ size_t const J = I+1;
+
+ using U = mp11::mp_at_c<variant<T...>, I>;
+
+ static_assert( std::is_nothrow_move_constructible<U>::value, "Logic error: U must be nothrow move constructible" );
+
+ U tmp( std::forward<A>(a)... );
+
+ _destroy();
+
+ st1_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
+ ix_ = J;
+ }
+};
+
+// not trivially destructible, double buffered
+template<class... T> struct variant_base_impl<false, false, T...>
+{
+ int ix_;
+ variant_storage<none, T...> st1_;
+ variant_storage<none, T...> st2_;
+
+ constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
+ {
+ }
+
+ template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() )
+ {
+ }
+
+ // requires: ix_ == 0
+ template<class I, class... A> void _replace( I, A&&... a )
+ {
+ ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
+ ix_ = I::value + 1;
+ }
+
+ //[&]( auto I ){
+ // using U = mp_at_c<mp_list<none, T...>, I>;
+ // st1_.get( I ).~U();
+ //}
+
+ struct _destroy_L1
+ {
+ variant_base_impl * this_;
+
+ template<class I> void operator()( I ) const noexcept
+ {
+ using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
+ this_->st1_.get( I() ).~U();
+ }
+ };
+
+ struct _destroy_L2
+ {
+ variant_base_impl * this_;
+
+ template<class I> void operator()( I ) const noexcept
+ {
+ using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
+ this_->st2_.get( I() ).~U();
+ }
+ };
+
+ void _destroy() noexcept
+ {
+ if( ix_ > 0 )
+ {
+ mp11::mp_with_index<1 + sizeof...(T)>( ix_, _destroy_L1{ this } );
+ }
+ else if( ix_ < 0 )
+ {
+ mp11::mp_with_index<1 + sizeof...(T)>( -ix_, _destroy_L2{ this } );
+ }
+ }
+
+ ~variant_base_impl() noexcept
+ {
+ _destroy();
+ }
+
+ constexpr std::size_t index() const noexcept
+ {
+ return ix_ >= 0? ix_ - 1: -ix_ - 1;
+ }
+
+ template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
+ {
+ size_t const J = I+1;
+
+ assert( ix_ == J || -ix_ == J );
+
+ constexpr mp11::mp_size_t<J> j{};
+ return ix_ >= 0? st1_.get( j ): st2_.get( j );
+ }
+
+ template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
+ {
+ // size_t const J = I+1;
+ // assert( ix_ == J || -ix_ == J );
+ // constexpr mp_size_t<J> j{};
+
+ return ix_ >= 0? st1_.get( mp11::mp_size_t<I+1>() ): st2_.get( mp11::mp_size_t<I+1>() );
+ }
+
+ template<std::size_t I, class... A> void emplace( A&&... a )
+ {
+ size_t const J = I+1;
+
+ if( ix_ >= 0 )
+ {
+ st2_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
+ _destroy();
+
+ ix_ = -static_cast<int>( J );
+ }
+ else
+ {
+ st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
+ _destroy();
+
+ ix_ = J;
+ }
+ }
+};
+
+} // namespace detail
+
+// in_place_type_t
+
+template<class T> struct in_place_type_t
+{
+};
+
+#if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
+
+template<class T> constexpr in_place_type_t<T> in_place_type{};
+
+#endif
+
+namespace detail
+{
+
+template<class T> struct is_in_place_type: std::false_type {};
+template<class T> struct is_in_place_type<in_place_type_t<T>>: std::true_type {};
+
+} // namespace detail
+
+// in_place_index_t
+
+template<std::size_t I> struct in_place_index_t
+{
+};
+
+#if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
+
+template<std::size_t I> constexpr in_place_index_t<I> in_place_index{};
+
+#endif
+
+namespace detail
+{
+
+template<class T> struct is_in_place_index: std::false_type {};
+template<std::size_t I> struct is_in_place_index<in_place_index_t<I>>: std::true_type {};
+
+} // namespace detail
+
+// is_nothrow_swappable
+
+namespace detail
+{
+
+namespace det2
+{
+
+using std::swap;
+
+template<class T> using is_swappable_impl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
+
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+
+template<class T> struct is_nothrow_swappable_impl_
+{
+ static constexpr bool value = noexcept(swap(std::declval<T&>(), std::declval<T&>()));
+};
+
+template<class T> using is_nothrow_swappable_impl = mp11::mp_bool< is_nothrow_swappable_impl_<T>::value >;
+
+#else
+
+template<class T> using is_nothrow_swappable_impl = typename std::enable_if<noexcept(swap(std::declval<T&>(), std::declval<T&>()))>::type;
+
+#endif
+
+} // namespace det2
+
+template<class T> struct is_swappable: mp11::mp_valid<det2::is_swappable_impl, T>
+{
+};
+
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+
+template<class T> struct is_nothrow_swappable: mp11::mp_eval_if<mp11::mp_not<is_swappable<T>>, mp11::mp_false, det2::is_nothrow_swappable_impl, T>
+{
+};
+
+#else
+
+template<class T> struct is_nothrow_swappable: mp11::mp_valid<det2::is_nothrow_swappable_impl, T>
+{
+};
+
+#endif
+
+} // namespace detail
+
+// variant
+
+template<class... T> class variant: private detail::variant_base<T...>
+{
+private:
+
+ using variant_base = detail::variant_base<T...>;
+
+private:
+
+ variant( variant const volatile& r ) = delete;
+ variant& operator=( variant const volatile& r ) = delete;
+
+public:
+
+ // constructors
+
+ template<class E1 = void, class E2 = mp11::mp_if<std::is_default_constructible< mp11::mp_first<variant<T...>> >, E1>>
+ constexpr variant()
+ noexcept( std::is_nothrow_default_constructible< mp11::mp_first<variant<T...>> >::value )
+ : variant_base( mp11::mp_size_t<0>() )
+ {
+ }
+
+ template<class E1 = void,
+ class E2 = mp11::mp_if<mp11::mp_all<detail::is_trivially_copy_constructible<T>...>, E1>
+ >
+ constexpr variant( variant const& r ) noexcept
+ : variant_base( static_cast<variant_base const&>(r) )
+ {
+ }
+
+private:
+
+ struct L1
+ {
+ variant_base * this_;
+ variant const & r;
+
+ template<class I> void operator()( I i ) const
+ {
+ this_->_replace( i, r._get_impl( i ) );
+ }
+ };
+
+public:
+
+ template<class E1 = void,
+ class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<detail::is_trivially_copy_constructible<T>...>>, E1>,
+ class E3 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<T>...>, E1>
+ >
+ variant( variant const& r )
+ noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
+ {
+ mp11::mp_with_index<sizeof...(T)>( r.index(), L1{ this, r } );
+ }
+
+ template<class E1 = void,
+ class E2 = mp11::mp_if<mp11::mp_all<detail::is_trivially_move_constructible<T>...>, E1>
+ >
+ constexpr variant( variant && r ) noexcept
+ : variant_base( static_cast<variant_base&&>(r) )
+ {
+ }
+
+private:
+
+ struct L2
+ {
+ variant_base * this_;
+ variant & r;
+
+ template<class I> void operator()( I i ) const
+ {
+ this_->_replace( i, std::move( r._get_impl( i ) ) );
+ }
+ };
+
+public:
+
+ template<class E1 = void,
+ class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<detail::is_trivially_move_constructible<T>...>>, E1>,
+ class E3 = mp11::mp_if<mp11::mp_all<std::is_move_constructible<T>...>, E1>
+ >
+ variant( variant && r )
+ noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
+ {
+ mp11::mp_with_index<sizeof...(T)>( r.index(), L2{ this, r } );
+ }
+
+ template<class U,
+ class Ud = typename std::decay<U>::type,
+ class E1 = typename std::enable_if< !std::is_same<Ud, variant>::value && !detail::is_in_place_index<Ud>::value && !detail::is_in_place_type<Ud>::value >::type,
+ class V = detail::resolve_overload_type<U&&, T...>,
+ class E2 = typename std::enable_if<std::is_constructible<V, U&&>::value>::type
+ >
+ constexpr variant( U&& u )
+ noexcept( std::is_nothrow_constructible<V, U&&>::value )
+ : variant_base( detail::resolve_overload_index<U&&, T...>(), std::forward<U>(u) )
+ {
+ }
+
+ template<class U, class... A, class I = mp11::mp_find<variant<T...>, U>, class E = typename std::enable_if<std::is_constructible<U, A&&...>::value>::type>
+ constexpr explicit variant( in_place_type_t<U>, A&&... a ): variant_base( I(), std::forward<A>(a)... )
+ {
+ }
+
+ template<class U, class V, class... A, class I = mp11::mp_find<variant<T...>, U>, class E = typename std::enable_if<std::is_constructible<U, std::initializer_list<V>&, A&&...>::value>::type>
+ constexpr explicit variant( in_place_type_t<U>, std::initializer_list<V> il, A&&... a ): variant_base( I(), il, std::forward<A>(a)... )
+ {
+ }
+
+ template<std::size_t I, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, A&&...>::value>::type>
+ constexpr explicit variant( in_place_index_t<I>, A&&... a ): variant_base( mp11::mp_size_t<I>(), std::forward<A>(a)... )
+ {
+ }
+
+ template<std::size_t I, class V, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, std::initializer_list<V>&, A&&...>::value>::type>
+ constexpr explicit variant( in_place_index_t<I>, std::initializer_list<V> il, A&&... a ): variant_base( mp11::mp_size_t<I>(), il, std::forward<A>(a)... )
+ {
+ }
+
+ // assignment
+ template<class E1 = void,
+ class E2 = mp11::mp_if<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>, E1>
+ >
+ BOOST_CXX14_CONSTEXPR variant& operator=( variant const & r ) noexcept
+ {
+ static_cast<variant_base&>( *this ) = static_cast<variant_base const&>( r );
+ return *this;
+ }
+
+private:
+
+ struct L3
+ {
+ variant * this_;
+ variant const & r;
+
+ template<class I> void operator()( I i ) const
+ {
+ this_->variant_base::template emplace<I::value>( r._get_impl( i ) );
+ }
+ };
+
+public:
+
+ template<class E1 = void,
+ class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>>, E1>,
+ class E3 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<T>..., std::is_copy_assignable<T>...>, E1>
+ >
+ BOOST_CXX14_CONSTEXPR variant& operator=( variant const & r )
+ noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
+ {
+ mp11::mp_with_index<sizeof...(T)>( r.index(), L3{ this, r } );
+ return *this;
+ }
+
+ template<class E1 = void,
+ class E2 = mp11::mp_if<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>, E1>
+ >
+ BOOST_CXX14_CONSTEXPR variant& operator=( variant && r ) noexcept
+ {
+ static_cast<variant_base&>( *this ) = static_cast<variant_base&&>( r );
+ return *this;
+ }
+
+private:
+
+ struct L4
+ {
+ variant * this_;
+ variant & r;
+
+ template<class I> void operator()( I i ) const
+ {
+ this_->variant_base::template emplace<I::value>( std::move( r._get_impl( i ) ) );
+ }
+ };
+
+public:
+
+ template<class E1 = void,
+ class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>>, E1>,
+ class E3 = mp11::mp_if<mp11::mp_all<std::is_move_constructible<T>..., std::is_move_assignable<T>...>, E1>
+ >
+ variant& operator=( variant && r )
+ noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
+ {
+ mp11::mp_with_index<sizeof...(T)>( r.index(), L4{ this, r } );
+ return *this;
+ }
+
+ template<class U,
+ class E1 = typename std::enable_if<!std::is_same<typename std::decay<U>::type, variant>::value>::type,
+ class V = detail::resolve_overload_type<U, T...>,
+ class E2 = typename std::enable_if<std::is_assignable<V&, U&&>::value && std::is_constructible<V, U&&>::value>::type
+ >
+ BOOST_CXX14_CONSTEXPR variant& operator=( U&& u )
+ noexcept( std::is_nothrow_constructible<V, U&&>::value )
+ {
+ std::size_t const I = detail::resolve_overload_index<U, T...>::value;
+ this->template emplace<I>( std::forward<U>(u) );
+ return *this;
+ }
+
+ // modifiers
+
+ template<class U, class... A,
+ class E = typename std::enable_if< mp11::mp_count<variant<T...>, U>::value == 1 && std::is_constructible<U, A&&...>::value >::type>
+ BOOST_CXX14_CONSTEXPR U& emplace( A&&... a )
+ {
+ using I = mp11::mp_find<variant<T...>, U>;
+ variant_base::template emplace<I::value>( std::forward<A>(a)... );
+ return _get_impl( I() );
+ }
+
+ template<class U, class V, class... A,
+ class E = typename std::enable_if< mp11::mp_count<variant<T...>, U>::value == 1 && std::is_constructible<U, std::initializer_list<V>&, A&&...>::value >::type>
+ BOOST_CXX14_CONSTEXPR U& emplace( std::initializer_list<V> il, A&&... a )
+ {
+ using I = mp11::mp_find<variant<T...>, U>;
+ variant_base::template emplace<I::value>( il, std::forward<A>(a)... );
+ return _get_impl( I() );
+ }
+
+ template<std::size_t I, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, A&&...>::value>::type>
+ BOOST_CXX14_CONSTEXPR variant_alternative_t<I, variant<T...>>& emplace( A&&... a )
+ {
+ variant_base::template emplace<I>( std::forward<A>(a)... );
+ return _get_impl( mp11::mp_size_t<I>() );
+ }
+
+ template<std::size_t I, class V, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, std::initializer_list<V>&, A&&...>::value>::type>
+ BOOST_CXX14_CONSTEXPR variant_alternative_t<I, variant<T...>>& emplace( std::initializer_list<V> il, A&&... a )
+ {
+ variant_base::template emplace<I>( il, std::forward<A>(a)... );
+ return _get_impl( mp11::mp_size_t<I>() );
+ }
+
+ // value status
+
+ constexpr bool valueless_by_exception() const noexcept
+ {
+ return false;
+ }
+
+ using variant_base::index;
+
+ // swap
+
+private:
+
+ struct L5
+ {
+ variant * this_;
+ variant & r;
+
+ template<class I> void operator()( I i ) const
+ {
+ using std::swap;
+ swap( this_->_get_impl( i ), r._get_impl( i ) );
+ }
+ };
+
+public:
+
+ void swap( variant& r ) noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>..., detail::is_nothrow_swappable<T>...>::value )
+ {
+ if( index() == r.index() )
+ {
+ mp11::mp_with_index<sizeof...(T)>( index(), L5{ this, r } );
+ }
+ else
+ {
+ variant tmp( std::move(*this) );
+ *this = std::move( r );
+ r = std::move( tmp );
+ }
+ }
+
+ // private accessors
+
+ using variant_base::_get_impl;
+
+ // converting constructors (extension)
+
+private:
+
+ template<class... U> struct L6
+ {
+ variant_base * this_;
+ variant<U...> const & r;
+
+ template<class I> void operator()( I i ) const
+ {
+ using J = mp11::mp_find<mp11::mp_list<T...>, mp11::mp_at<mp11::mp_list<U...>, I>>;
+ this_->_replace( J{}, r._get_impl( i ) );
+ }
+ };
+
+public:
+
+ template<class... U,
+ class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
+ variant( variant<U...> const& r )
+ noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<U>...>::value )
+ {
+ mp11::mp_with_index<sizeof...(U)>( r.index(), L6<U...>{ this, r } );
+ }
+
+private:
+
+ template<class... U> struct L7
+ {
+ variant_base * this_;
+ variant<U...> & r;
+
+ template<class I> void operator()( I i ) const
+ {
+ using J = mp11::mp_find<mp11::mp_list<T...>, mp11::mp_at<mp11::mp_list<U...>, I>>;
+ this_->_replace( J{}, std::move( r._get_impl( i ) ) );
+ }
+ };
+
+public:
+
+ template<class... U,
+ class E2 = mp11::mp_if<mp11::mp_all<std::is_move_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
+ variant( variant<U...> && r )
+ noexcept( mp11::mp_all<std::is_nothrow_move_constructible<U>...>::value )
+ {
+ mp11::mp_with_index<sizeof...(U)>( r.index(), L7<U...>{ this, r } );
+ }
+
+ // subset (extension)
+
+private:
+
+ template<class... U, class V, std::size_t J, class E = typename std::enable_if<J != sizeof...(U)>::type> static constexpr variant<U...> _subset_impl( mp11::mp_size_t<J>, V && v )
+ {
+ return variant<U...>( in_place_index_t<J>(), std::forward<V>(v) );
+ }
+
+ template<class... U, class V> static variant<U...> _subset_impl( mp11::mp_size_t<sizeof...(U)>, V && /*v*/ )
+ {
+ detail::throw_bad_variant_access();
+ }
+
+private:
+
+ template<class... U> struct L8
+ {
+ variant * this_;
+
+ template<class I> variant<U...> operator()( I i ) const
+ {
+ using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
+ return this_->_subset_impl<U...>( J{}, this_->_get_impl( i ) );
+ }
+ };
+
+public:
+
+ template<class... U,
+ class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
+ BOOST_CXX14_CONSTEXPR variant<U...> subset() &
+ {
+ return mp11::mp_with_index<sizeof...(T)>( index(), L8<U...>{ this } );
+ }
+
+private:
+
+ template<class... U> struct L9
+ {
+ variant const * this_;
+
+ template<class I> variant<U...> operator()( I i ) const
+ {
+ using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
+ return this_->_subset_impl<U...>( J{}, this_->_get_impl( i ) );
+ }
+ };
+
+public:
+
+ template<class... U,
+ class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
+ constexpr variant<U...> subset() const&
+ {
+ return mp11::mp_with_index<sizeof...(T)>( index(), L9<U...>{ this } );
+ }
+
+private:
+
+ template<class... U> struct L10
+ {
+ variant * this_;
+
+ template<class I> variant<U...> operator()( I i ) const
+ {
+ using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
+ return this_->_subset_impl<U...>( J{}, std::move( this_->_get_impl( i ) ) );
+ }
+ };
+
+public:
+
+ template<class... U,
+ class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
+ BOOST_CXX14_CONSTEXPR variant<U...> subset() &&
+ {
+ return mp11::mp_with_index<sizeof...(T)>( index(), L10<U...>{ this } );
+ }
+
+#if !BOOST_WORKAROUND(BOOST_GCC, < 40900)
+
+ // g++ 4.8 doesn't handle const&& particularly well
+
+private:
+
+ template<class... U> struct L11
+ {
+ variant const * this_;
+
+ template<class I> variant<U...> operator()( I i ) const
+ {
+ using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
+ return this_->_subset_impl<U...>( J{}, std::move( this_->_get_impl( i ) ) );
+ }
+ };
+
+public:
+
+ template<class... U,
+ class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
+ constexpr variant<U...> subset() const&&
+ {
+ return mp11::mp_with_index<sizeof...(T)>( index(), L11<U...>{ this } );
+ }
+
+#endif
+};
+
+// relational operators
+
+namespace detail
+{
+
+template<class... T> struct eq_L
+{
+ variant<T...> const & v;
+ variant<T...> const & w;
+
+ template<class I> constexpr bool operator()( I i ) const
+ {
+ return v._get_impl( i ) == w._get_impl( i );
+ }
+};
+
+} // namespace detail
+
+template<class... T> constexpr bool operator==( variant<T...> const & v, variant<T...> const & w )
+{
+ return v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::eq_L<T...>{ v, w } );
+}
+
+namespace detail
+{
+
+template<class... T> struct ne_L
+{
+ variant<T...> const & v;
+ variant<T...> const & w;
+
+ template<class I> constexpr bool operator()( I i ) const
+ {
+ return v._get_impl( i ) != w._get_impl( i );
+ }
+};
+
+} // namespace detail
+
+template<class... T> constexpr bool operator!=( variant<T...> const & v, variant<T...> const & w )
+{
+ return v.index() != w.index() || mp11::mp_with_index<sizeof...(T)>( v.index(), detail::ne_L<T...>{ v, w } );
+}
+
+namespace detail
+{
+
+template<class... T> struct lt_L
+{
+ variant<T...> const & v;
+ variant<T...> const & w;
+
+ template<class I> constexpr bool operator()( I i ) const
+ {
+ return v._get_impl( i ) < w._get_impl( i );
+ }
+};
+
+} // namespace detail
+
+template<class... T> constexpr bool operator<( variant<T...> const & v, variant<T...> const & w )
+{
+ return v.index() < w.index() || ( v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::lt_L<T...>{ v, w } ) );
+}
+
+template<class... T> constexpr bool operator>( variant<T...> const & v, variant<T...> const & w )
+{
+ return w < v;
+}
+
+namespace detail
+{
+
+template<class... T> struct le_L
+{
+ variant<T...> const & v;
+ variant<T...> const & w;
+
+ template<class I> constexpr bool operator()( I i ) const
+ {
+ return v._get_impl( i ) <= w._get_impl( i );
+ }
+};
+
+} // namespace detail
+
+template<class... T> constexpr bool operator<=( variant<T...> const & v, variant<T...> const & w )
+{
+ return v.index() < w.index() || ( v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::le_L<T...>{ v, w } ) );
+}
+
+template<class... T> constexpr bool operator>=( variant<T...> const & v, variant<T...> const & w )
+{
+ return w <= v;
+}
+
+// visitation
+namespace detail
+{
+
+template<class T> using remove_cv_ref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+
+template<class T, class U> struct copy_cv_ref
+{
+ using type = T;
+};
+
+template<class T, class U> struct copy_cv_ref<T, U const>
+{
+ using type = T const;
+};
+
+template<class T, class U> struct copy_cv_ref<T, U volatile>
+{
+ using type = T volatile;
+};
+
+template<class T, class U> struct copy_cv_ref<T, U const volatile>
+{
+ using type = T const volatile;
+};
+
+template<class T, class U> struct copy_cv_ref<T, U&>
+{
+ using type = typename copy_cv_ref<T, U>::type&;
+};
+
+template<class T, class U> struct copy_cv_ref<T, U&&>
+{
+ using type = typename copy_cv_ref<T, U>::type&&;
+};
+
+template<class T, class U> using copy_cv_ref_t = typename copy_cv_ref<T, U>::type;
+
+template<class F> struct Qret
+{
+ template<class... T> using fn = decltype( std::declval<F>()( std::declval<T>()... ) );
+};
+
+template<class L> using front_if_same = mp11::mp_if<mp11::mp_apply<mp11::mp_same, L>, mp11::mp_front<L>>;
+
+template<class V> using apply_cv_ref = mp11::mp_product<copy_cv_ref_t, remove_cv_ref_t<V>, mp11::mp_list<V>>;
+
+template<class F, class... V> using Vret = front_if_same<mp11::mp_product_q<Qret<F>, apply_cv_ref<V>...>>;
+
+} // namespace detail
+
+template<class F> constexpr auto visit( F&& f ) -> decltype(std::forward<F>(f)())
+{
+ return std::forward<F>(f)();
+}
+
+namespace detail
+{
+
+template<class F, class V1> struct visit_L1
+{
+ F&& f;
+ V1&& v1;
+
+ template<class I> auto operator()( I ) const -> Vret<F, V1>
+ {
+ return std::forward<F>(f)( unsafe_get<I::value>( std::forward<V1>(v1) ) );
+ }
+};
+
+} // namespace detail
+
+template<class F, class V1> constexpr auto visit( F&& f, V1&& v1 ) -> detail::Vret<F, V1>
+{
+ return mp11::mp_with_index<variant_size<V1>>( v1.index(), detail::visit_L1<F, V1>{ std::forward<F>(f), std::forward<V1>(v1) } );
+}
+
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) || BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+
+namespace detail
+{
+
+template<class F, class A> struct bind_front_
+{
+ F&& f;
+ A&& a;
+
+ template<class... T> auto operator()( T&&... t ) -> decltype( std::forward<F>(f)( std::forward<A>(a), std::forward<T>(t)... ) )
+ {
+ return std::forward<F>(f)( std::forward<A>(a), std::forward<T>(t)... );
+ }
+};
+
+template<class F, class A> bind_front_<F, A> bind_front( F&& f, A&& a )
+{
+ return bind_front_<F, A>{ std::forward<F>(f), std::forward<A>(a) };
+}
+
+template<class F, class V1, class V2> struct visit_L2
+{
+ F&& f;
+
+ V1&& v1;
+ V2&& v2;
+
+ template<class I> auto operator()( I ) const -> Vret<F, V1, V2>
+ {
+ auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
+ return visit( f2, std::forward<V2>(v2) );
+ }
+};
+
+} // namespace detail
+
+template<class F, class V1, class V2> constexpr auto visit( F&& f, V1&& v1, V2&& v2 ) -> detail::Vret<F, V1, V2>
+{
+ return mp11::mp_with_index<variant_size<V1>>( v1.index(), detail::visit_L2<F, V1, V2>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2) } );
+}
+
+namespace detail
+{
+
+template<class F, class V1, class V2, class V3> struct visit_L3
+{
+ F&& f;
+
+ V1&& v1;
+ V2&& v2;
+ V3&& v3;
+
+ template<class I> auto operator()( I ) const -> Vret<F, V1, V2, V3>
+ {
+ auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
+ return visit( f2, std::forward<V2>(v2), std::forward<V3>(v3) );
+ }
+};
+
+} // namespace detail
+
+template<class F, class V1, class V2, class V3> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3 ) -> detail::Vret<F, V1, V2, V3>
+{
+ return mp11::mp_with_index<variant_size<V1>>( v1.index(), detail::visit_L3<F, V1, V2, V3>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2), std::forward<V3>(v3) } );
+}
+
+namespace detail
+{
+
+template<class F, class V1, class V2, class V3, class V4> struct visit_L4
+{
+ F&& f;
+
+ V1&& v1;
+ V2&& v2;
+ V3&& v3;
+ V4&& v4;
+
+ template<class I> auto operator()( I ) const -> Vret<F, V1, V2, V3, V4>
+ {
+ auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
+ return visit( f2, std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) );
+ }
+};
+
+} // namespace detail
+
+template<class F, class V1, class V2, class V3, class V4> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3, V4&& v4 ) -> detail::Vret<F, V1, V2, V3, V4>
+{
+ return mp11::mp_with_index<variant_size<V1>>( v1.index(), detail::visit_L4<F, V1, V2, V3, V4>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) } );
+}
+
+#else
+
+template<class F, class V1, class V2, class... V> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V&&... v ) -> detail::Vret<F, V1, V2, V...>
+{
+ return mp11::mp_with_index<variant_size<V1>>( v1.index(), [&]( auto I ){
+
+ auto f2 = [&]( auto&&... a ){ return std::forward<F>(f)( detail::unsafe_get<I.value>( std::forward<V1>(v1) ), std::forward<decltype(a)>(a)... ); };
+ return visit( f2, std::forward<V2>(v2), std::forward<V>(v)... );
+
+ });
+}
+
+#endif
+
+// specialized algorithms
+template<class... T,
+ class E = typename std::enable_if<mp11::mp_all<std::is_move_constructible<T>..., detail::is_swappable<T>...>::value>::type>
+void swap( variant<T...> & v, variant<T...> & w )
+ noexcept( noexcept(v.swap(w)) )
+{
+ v.swap( w );
+}
+
+} // namespace variant2
+} // namespace boost
+
+#if defined(_MSC_VER) && _MSC_VER < 1910
+# pragma warning( pop )
+#endif
+
+#endif // #ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED
diff --git a/boost/version.hpp b/boost/version.hpp
index 98ce61a15e..912a59c8e2 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 107000
+#define BOOST_VERSION 107100
//
// 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_70"
+#define BOOST_LIB_VERSION "1_71"
#endif
diff --git a/boost/yap/user_macros.hpp b/boost/yap/user_macros.hpp
index ea25b4cd08..6827ba3ca9 100644
--- a/boost/yap/user_macros.hpp
+++ b/boost/yap/user_macros.hpp
@@ -278,7 +278,7 @@
resulting expression.
The \a rhs parameter to each of the defined overloads may be any type,
- including an expression, except that the overloads are cosntrained by
+ including an expression, except that the overloads are constrained by
std::enable_if<> not to conflict with the assignment and move assignement
operators. If \a rhs is a non-expression, it is wrapped in a terminal
expression.
@@ -352,7 +352,7 @@
resulting expression.
The \a rhs parameter to each of the defined overloads may be any type,
- including an expression, except that the overloads are cosntrained by
+ including an expression, except that the overloads are constrained by
std::enable_if<> not to conflict with the assignment and move assignement
operators. If \a rhs is a non-expression, it is wrapped in a terminal
expression.